Wednesday, October 15, 2008

A reminder of the "Object Preferences" feature in the Debugger in JDeveloper 11

Worth mentioning again now 11 is final production as this is a really useful feature that many people don't find for a long time.

Basically it allow the user to control what is displayed by the debugger, up to and including the invocation of accessor methods.

Applying Patches to JDeveloper/WebLogic using Smart Update. (Fixing the ADF vs WebService issue in 11)

A really nasty bug that made it in to the boxer release is the total failure if you mix ADF and web services in the same application. Fortunately we have a patch for this now; but it is not obvious how you might go about applying this if your are not familiar with the bea smart update tool.

First of all you need a bea account, you can get this from support.bea.com. I am told that you wont need a support license for this particular patch. Then you need to go to %ORACLE_HOME%/utils/bsu and run either bsu.sh or bsu.cmd depending on your platform.

When you are logged in make select the "JDeveloper" installation that you want to patch. Don't confuse this other plain "WebLogic" installs you might have hanging around.

Then make sure the "Get Patches" tab is selected and select the menu item Patches -> Retrieve Patch. In this case the patch ID is "RFRS" and the passcode "VGJ16G15". Download the patch, just agree to any dialogs that come up.

Now you can go to the "Manage Patches" tab to find the patch you have just downloaded and press the apply icon.

The patch should now move to the "Default" table and is now ready to test. Restart WebLogic | JDeveloper and hopefully the problem will go away.

In case google is watching you expect the following stack trace when deploying a web service if this patch is not applied:

Target state: deploy failed on Server srg 
 [java] java.lang.NullPointerException 
 [java]     at weblogic.wsee.wsdl.WsdlTypes.collectNamespaces(WsdlTypes.java:213) 
 [java]     at weblogic.wsee.wsdl.WsdlTypes.collectNamespaces(WsdlTypes.java:229) 
 [java]     at weblogic.wsee.wsdl.WsdlTypes.collectNamespaces(WsdlTypes.java:229) 
 [java]     at weblogic.wsee.wsdl.WsdlTypes.parse(WsdlTypes.java:151) 
 [java]     at weblogic.wsee.wsdl.WsdlDefinitions.parseChild(WsdlDefinitions.java:520) 

Monday, October 13, 2008

Jersey 1.0 Released

The first production release of the reference implementation of Jersey in now out there to play with. Previous notes on weblogic / jdeveloper still apply as far as I can tell.

Wednesday, October 8, 2008

What happened to extension X in JDeveloper 11? (Worked example with Spring extension)

Warning, this is a workaround and I give absolutely no warranty as to the results of trying this. Only use this if you really need a particular extension in order to move forward. It might may your JDeveloper to become unstable and cause your pets to come out in a rash. Right health and safety over.....

Those of you how are moving up to JDeveloper from 10.1.3 will notice that some of the extensions you know and love are not yet available in 11. This is mostly likely because the extension developer has been conservative in there bundle definition to restrict the usage in future versions. The good news is that that APIs for JDeveloper were frozen in 10.1.3 and for most part well written extensions should work. (You will note that the ones I have worked on will turn up in the center already as I tend to be more pragmatic about such things.)

You can work around this though with a little bit of work. First of all we need to capture the traffic between JDeveloper and the update center. To do this start the the HTTP Analyzer in JDeveloper. (View->HTTP Analyzer, Then press the green start start button) Then run the update tool Help->Check for Updates and proceed to the page you would normally see you extensions on. You can press cancel now as we have captured all the important information.

In my build the most important request goes to "http://www.oracle.com/technology/products/jdev/101/update/exchange.xml". So do a quick search of the response text, and yes you do have to copy the text to another editor to do this I have logged a bug for this, to find the extension you want. In my case I needed the spring extension and found this:

  <u:update id="oracle.jdeveloper.spring2">
    <u:name>JDeveloper Spring 2.5 Support</u:name>
    <u:version>08.01.09.01</u:version>
    <u:author>Oracle</u:author>
    <u:author-url>http://www.oracle.com/technology/products/jdev/htdocs/partners/addins/exchange/spring/spring-extension.html</u:author-url>

    <u:description>
        Adds support for creating and editing Spring 2.5 bean defintions. This addin will create the Spring 2.5.1 library and register the relevant XSDs and DTDs
        with the IDE to provide a productive editing experience for Spring definitions.
    </u:description>

    <!--u:post-startup-hook>oracle.jdevimpl.spring.addin.SpringAddinInstaller</u:post-startup-hook-->

    <u:requirements>
      <u:requires-extension id="oracle.jdeveloper"
                            minVersion="10.1.3.36.73" 
                            maxVersion="10.1.3.9999" />
    </u:requirements>  
<u:bundle-url>http://download.oracle.com/otn/java/jdeveloper/10131/extensions/JDeveloperSpring2.zip</u:bundle-url>
  </u:update>

Note the "requires" entry is the one that is causing problem. So we ignore this and just download the related zip file and place the contents in .../jdeveloper/jdev/extensions/ directory. This will not run any installer that comes with the extension; but should work in most cases.

In the spring case though you need to modify the name of the install directories. It appears that the long version numbers aren't liked by the more recent build of JDeveloper. You can discover this by looking at the libraries defined by the extension, Tools->Manage Libraries->Spring 2.5, and seeing where they are trying to find the jar files. In this case it seems we have to rename the extension jar and directory from "oracle.jdeveloper.spring2.08.01.09.01" to "oracle.jdeveloper.spring2.8". Now in theory you shouldn't need the version numbers at all; but but removing them didn't work in this case.

Next time you start JDeveloper you should find that in most cases the extension will work without problems. Even if you have an issue this should tide you over until the extension developer gets time to put another release out. When they do you may have to manually delete the extension before trying to install the new true extension from the update center. Also please disable this extension before reporting bugs on the forum to work out whether they are causing problems.

Right now I need to go back and figure out what I was working on and try to remember why I wanted the spring extension!

Tuesday, October 7, 2008

Overview of JAX-RS 1.0 and Jersey extensions.

Good overview of JAX-RS 1.0 and hopefully in a few days one for those extensions that are part of Jersey and not part of the specification yet.

JDeveloper 11 goes production, horrah!

Finally you can see what we have been up to all these years in a full production version. It appears that the issues with the download page that were seen earlier today have been fixed.

This version is built on top of the very new Weblogic 10.3 so you get more toys for your money. Collateral for 11 should start to pop up on OTN in due course.

One final point, JDeveloper now comes as an installer. So run the jar file, don't try to unzip it.

Monday, October 6, 2008

JAX-RS / Jersey targeted for the 13th of October?

Based on a quote from Paul Sandoz JAX-RS / Jersey goes production on the 13th. As noted in my previous post there are still some work aroundable issues; but it will be nice to have a library that is claimed to be production quality.

Thursday, October 2, 2008

Running JAX-RS/Jersey/JSR311 on weblogic

Please check the bottom of this post for the latest information.

Now that JSR311 has been approved I thought it was time to have a quick go at running a simple hello world service using JDeveloper / Weblogic. These instructions should give you enough of a hint though if you are using Ant/Eclipse or some other tool to build your services. Turns out for weblogic there a few issues to be work around first before you will get a running service.

First of all you need to download some jar files, not quite sure why but the jersey folks seem to go about of there way to make things harder for you if you are not using Maven. You need to follow the "Download" link from the main jersey page. (I can't provide a hyperlink as this page moves with each release, this instructions are based on 0.9). The minimum list of jars you need to run simple services is:

  • jersey-bundle-*.jar
  • jsr311-api.jar
  • asm-*.jar

In JDeveloper create a new library against a project with these three jar files in them. Make sure you mark the library as "Deploy Always". For the moment you wont find these jars in a j2ee server.

In the project you want to create you RESTful services in you need to create a web.xml that contains a reference to the root JAX-RS servlet. This wont be required when we get JEE6; but it doesn't take too much effort to put the extra entries in place. Once you have finished your web.xml will look like:

<?xml version = '1.0' encoding = 'ISO-8859-1'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
    <description>Empty web.xml file for Web Application</description>
    <session-config>
        <session-timeout>35</session-timeout>
    </session-config>
    <mime-mapping>
        <extension>html</extension>
        <mime-type>text/html</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>txt</extension>
        <mime-type>text/plain</mime-type>
    </mime-mapping>
    <servlet>
        <display-name>JAX-RS Servlet</display-name>
        <servlet-name>jersey</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
            <param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>project1</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

You need to edit the value for "com.sun.jersey.config.property.packages" to contain a ';' separated list of package names to search. The default configuration class that scans the entire classpath doesn't work on weblogic. Hopefully they will fix this before 1.0 comes out.

So let quickly create a hello world service so we can test things out:

1  package project1;
 2  
 3  import javax.ws.rs.Path;
 4  import javax.ws.rs.GET;
 5  import javax.ws.rs.Produces;
 6  
 7  
 8  @Path("/helloworld")
 9  public class HelloRS {
10   
11      // The Java method will process HTTP GET requests
12      @GET
13      // The Java method will produce content identified by the MIME Media
14      // type "text/plain"
15      @Produces("text/plain")
16      public String getClichedMessage() {
17          // Return some cliched textual content
18          return "Hello World";
19      }
20  }

You have a little bit more work to do to get this working, since JDeveloper doesn't "know" about JAX-RS you have to deploy rather than just run this java file So create a WAR file deployment profile for the project and a EAR file deployment profile that contains the WAR at the application level. Finally create a weblogic-application.xml deployment descriptor for the EAR and add the following text. (In the application navigator go to the "Application Resource Section", then Descriptors->META-INF and the context menu "Create Weblogic Descriptor".

<?xml version = '1.0' encoding = 'ISO-8859-1'?>
<weblogic-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-application.xsd" xmlns="http://www.bea.com/ns/weblogic/weblogic-application">
  <prefer-application-packages>
    <package-name>org.objectweb.*</package-name>
  </prefer-application-packages>
</weblogic-application>

This makes sure that the version of asm that comes with JAX-RS overrides the one that is built into weblogic. Otherwise you get a method not found error when the service deploys. You should now be able to deploy the service and test using a URL such as "http://localhost:7101/Application1-Project1-context-root/helloworld". The context root and machine/port will of course vary depending on your environment.

You can test this in a web browser, or in JDeveloper you can test using the HTTP Analyzer. View->HTTP Analyzer, Create New Message toolbar button and navigate to the "HTTP Content" tab. Put your URL in at the top and change the method to "GET" rather than the default "POST". Send the message as you should get back "Hello World" in plain text.

Right no time left to play today, back to fixing bugs.

Update 9 Dec '08:

There is an alternative to creating the weblogic-application.xml file that I discovered recently. I wasn't happy with this solution as it affected the entire EAR file. Instead you can create a "weblogic.xml" under WEB-INF that looks like this:

<?xml version = '1.0' encoding = 'ISO-8859-1'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app.xsd" xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
<container-descriptor>
    <prefer-web-inf-classes>true</prefer-web-inf-classes>
  </container-descriptor>
</weblogic-web-app>

This has the advantage of only affecting the .war file you are deploying the restful services in. Also I have found out that this problem with the clashing jar files appears to have gone away in the "next" big release of weblogic, but I can't promise you when or even if you will see this fix.

Update 13 Feb 13 '09: With the release of Jersery 1.0.2 you can now download with the basic dependencies, the json libraries and javadoc from the download page. This makes it much easier for non maven users to pick up and use it. Make sure you include both the -server and -core libraries as the -bundle version is not present in the zip.

  • jersey-core-*.jar
  • jersey-server-*.jar
  • jsr311-api-1.0.jar
  • asm-*.jar

Update 24 July '09: You can now download all the core dependencies in one big lump in the jersey-archive take a look at the download page for details.

Update 24 July '09: For weblogic server 10.3.1 aka the R1 release you no longer have to use the "prefer-web-inf-classes" modifier as the namespace in the internal copy of asm has been changed.

Update 12th August '09: (We think this only work for the yet unreleased R11PS1/10.3.2 version) For weblogic server 10.x you can can fix the annotation scanner issue so you no longer have to specify the package location. The failure is caused because ServletContext.getRealPath(...) returns null when you deploy an application as a jar file. You can work around this with the fix for weblogic issue CR299135.

In the simplest case this means your web.xml simplifies to:

<?xml version = '1.0' encoding = 'ISO-8859-1'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
    <servlet>
        <display-name>JAX-RS Servlet</display-name>
        <servlet-name>jersey</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

You could create a weblogic.xml under META-INF, see similar instructions before as to how to create weblogic-webservices.xml:

<?xml version = '1.0' encoding = 'ISO-8859-1'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
                  xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
  <container-descriptor>
    <show-archived-real-path-enabled>true</show-archived-real-path-enabled>
  </container-descriptor>
</weblogic-web-app>

Or make the changes to config.xml mentioned in the CR' above.

Update 1st December '09: Jersey issue 32 has been resolved, if you pull the latest 1.5ea build you should be able to deploy with no workaround. JDeveloper R11 PS1 will unfortunately still create the weblogic.xml automatically; but we can fix this in a future release once 1.5 is production.

Update 11th of March '10: Some final issues, resolved in Jersey 1.1.5.1 specifically for weblogic. Resolved the null pointer in web scanner and some problems with package level filtering that has been reported here.

Update 25 of May '11: Some problems running Jersey with the Oracle XDK in the latest versions of JDeveloper.

Wednesday, October 1, 2008

Java, XDK, DOM trees and "instanceof"

Ran into an interesting bug today where code would run one way on the plain xml parser that comes with Java and fail when running with the Oracle XML Parser (XDK).:

public void collectNamespaces(Element element, Map collection)
{
   NamedNodeMap nam = element.getAttributes();
   assert nam!=null : "Attribute map can't be null";

   // Do something with the attributes
   //

   Node parent = element.getParentNode();
   if (parent!=null && parent instanceof Element)
   {
      collectNamespaces((Element)parent, collection);
   }
}

If you ran with the XDK, the last turn of the recursion would have element being an instance of XMLDocument, the XDK implementation of Document, which returns null for getAttributes. Now getAttributes should never return null for an Element and a quick look at org.w3c.dom.Document suggests it extends "org.w3c.dom.Node". So how did we get to element being assigned with a document instance?

It turns out that internally XMLDocument extends XMLElement which implements "org.w3c.dom.Element". It should be free to do this internally and only the instanceof is showing up this problem. But how would the code have been written to not have seen this problem? Well it turns on that Node.getNodeType provide you with enough information to write this code without "instanceof" or casting. (Turns out that getAttributes() is on the Node interface).

public void collectNamespaces(Node element, Map collection)
{
   assert element.getNodeType() == Node.ELEMENT_NODE : "Should only accept Element for namespace lookup"
   NamedNodeMap nam = element.getAttributes();
   assert nam!=null : "Attribute map can't be null";

   // Do something with the attributes
   //

   Node parent = element.getParentNode();
   if (parent!=null && parent.getNodeType()==Node.ELEMENT_NODE)
   {
      collectNamespaces(parent, collection);
   }
}

In general the lesson here is to use instanceof only where there isn't another way of doing things. It can tell you a little bit too much about the class you are working with. Sometimes you really don't need to know it's ancestry in that much detail.