Showing posts with label jdeveloper. Show all posts
Showing posts with label jdeveloper. Show all posts

Thursday, September 20, 2012

So what credentials do you need?

One of the features that I am very proud of in the HTTP Analyzer in JDeveloper is the ability to test a SOAP service with the minimum of fuss. Rather than having to configure security headers and understand WS-Policy we make use of the WLS JAX-WS client to read and interpret the policies defined in the WSDL and then apply abstracted credentials.

It turns out that this feature is very popular; but there is some confusion about just what information you might need to provide for a particular policy. So here is a simple summary of what is required for what type of policy.

Username Token


The simplest page just ask for a username and password. You are going to need this for policies that contains the phrase usernametoken, username, UNT or even HttpBasic and HttpDigest. The policy dictates where the values end up whether they be in an HTTP header or a WS-Security SOAP header.




X509 Certificates


The X509 panel is the most powerful and the most misunderstood. On this panel you can define a set of certificates and keys for both the client and the server.



The simplest version of this panel would be one that just contains the server key store. This is sufficient in most policy to be able to send a server an encrypted message and receive a message back. (In the most common case the server certificate is used to encrypt a symmetrical key, most likely AES,  that can be used to decrypt the message being received.)

You will also need this to verify messages that are signed by the server.

If you need to server to trust that you send the message with signing then you have to provide a identity in the form of a Public/Private key that can be used to encrypt the outgoing hashes used to sign the message. 

This client identity can also be used in leu of the username token described earlier. In the most common policy I have worked with the CN of the public certificate is used as the user identity. 

Http Keystores


Some policies will make use of a Https channel to send messages, and like the x509 certificate panel the settings come in both client and server side store.

In the simplest case this panel will just be configured with a "Trusted Certificates Keystore", so this will list with certificates or certificate signing authorities are going to be trusted by the analyser. In order to make this as easy as possible by default we append the "CA" certificates that come with Java so you can by default connect to most publish websites without any further configuration.



This will normally be enough unless the policy is defined as 2-Way HTTPS, most of the OWSM https policies I have worked with are 2-Way by default. The WLS ones tend to specify this explicitly. In the 2-Way case you again need to prove the identity of the client, and the only way of doing this is going to be with a Public/Private key that the server trusts.

STS Configuration

The final panel regards working with policies that require SAML tokens; JDeveloper is unable to issue SAML tokens itself so instead it need to get hold of a token from a STS store that is trusted by the server you are in contact with.

In this case you need to specify the URL of the endpoint of the STS service along with a security policy that will match that on the sever side. This is unfortunately a static list and has to be figured out manually. Perhaps this is something that can be improved on in a later release.


On important feature to note is that when connecting to the STS store the analyser will be using values from the other three panels that we have discussed. This might be important if you are having trouble setting up a connection.

Wednesday, June 15, 2011

Working around the need for a network connection in Spring and WebLogic SCA tooling in JDeveloper

Unfortunately the Spring tooling we have in JDeveloper 11.1.2 and PS5 contains a bug where it will try to access the network for a .dtd in order to validate the xml files. If you are running the HTTP Analyzer you might see something like the following:

This is fine if you have a network connection, if annoying, but with a timeout of 5 minutes in some cases it can be really annoying if you are trying to work where you cannot see the internet as a whole.

We are going to use a feature of the HTTP Analyzer to use a recording of this response to pretend to be the service in question. For of all we need a log file that contains the response in question, so select the message and press the save button:

Then we have to create a Tape Rule which allows the analyzer to respond using messages from a log file in response to request to a particular URL:

You need to set up the rule as follows, note the reference URL is not part of the definition; but can be used to validate the rule filter settings.

And you should be good to go, next time you start up JDeveloper start the HTTP Analyzer first, and you should see that the messages are being provided by the tape rule rather than the network.

We don't have a handy way to start the analyzer when the tool does; so you have to be careful not to have any open editors. But for some cases this is going to be a useful workaround.

Tuesday, May 10, 2011

JDeveloper, the Endorsed Directory, bootclasspath, and JAX-WS 2.2.x

I have been working with JAX-WS 2.2.x recently and one of problem you might fact whilst playing with a client is that it uses more recent version of the JAX-WS API than that supplied with JDK 1.6. This shouldn't be a problem normally but there are some issues that might get in your way when using JDeveloper.

The first thing to note is that I am going to ignore the standard advice to user the java.endorsed.dirs system property as it can only specify a directory and not individual jar files. This is not always a problem; but if your jars are not packaged in a convenient way it means you have to move then to a new directory. Instead I am going for the slightly less standard -Xbootclasspath/p: property which prepends the jars to the boot classpath with much the same effect and I can specify the paths to individual jars. I will note with the screen grabs where you might go differently if you want to ignore this advice.

First things first you need to configure the compiler otherwise when you try to compile a web services client, in this case, you find error messages relating to the constructors on the Service class. You can find these settings under project properties. You could use the -endorsedpath here if you wish. For my purposes I had to place both the jax-xml-bind.jar and jax-xml-ws.jar on the bootclasspath. Of course use you platform specific path separator between the two paths. (If you are doing JAX-WS you are going to need the matching version of JAX-B)

Unfortunately you might find that this point that the project will fail to compile due to bug 12538161, there is a workaround which is to ask the compilation to happen as a separate process. This is going to be slightly slower; but in most cases you are not going to notice the difference.

Depending on your deployment context you might also like to update the run options for the your project, again I have used the bootclasspath but you could use the -Djava.endorsed.dirs depending on how you dependencies are laid out.

You can compile and run against the new API which will solve 99% of problem in the area. Fortunately only a few Java API's are packaged in this way. Hopefully in JDK 8 we can get the modularization sorted out so this sort of thing will be less of a problem.

Monday, April 11, 2011

Generating an inline schema in JDeveloper

A question that comes up now and then is how to generate a WSDL with the Schema in-line rather than as a separate file. This is required for certain mobile platforms and in particular Siebel Tools. This feature wasn't added to the JAX-WS RI until version 2.2.1 which is ahead of the version use in JDeveloper. It is possible to get some integration using the external tools command to make use of a later version of this tool in JDeveloper.

To get this to work you first need to download JAX-WS RI 2.2.1 or later. The configuration is similar to what we have used previously on this blog with a few specific modifications.

The program executable is simply the location of the wsgen.sh or wsget.bat file that comes with the RI download. The second line is more complicated:

-Xendorsed -d ${project.outputdirectory} -s ${project.outputdirectory} -cp ${project.outputdirectory};${project.classpath} ${target.class} -r ${file.dir} -wsdl  -inlineSchemas

Reading left to right we are: making sure we used the endorsed property to use the updated API; specifying the project classes directory for any output; specifying the project classpath; the class name from the current selection; where the wsdl file should be written out, the same one as the java file; and finally that we want to generate a wsdl and that it should be inline.

In the rest of the wizard you are likely to want to configure the tool to appear in the navigator and only appear for java source files. All pretty vanilla stuff. Once this is configured you should have a menu item you can invoke from the JDeveloper UI. After you invoke this action if you didn't check re-load external tools in the wizard you need to press the refresh button to see any changes.

There is one remaining manual step and that is to associate the wsdl with the source file, to do this you simply need to update the wsdlLocation attribute:

package webservice;

import javax.jws.WebService;

@WebService(wsdlLocation = "/webservice/HelloService.wsdl")
public class Hello {
    public String hello(String name) {
        return "";
    }
}

This will now deploy with the new compact all in one wsdl document. JDeveloper will notice you have a file and tell you if the files get out of sync; but you will of course need to use your external tool command otherwise you will loose your in-line schema.

Friday, September 3, 2010

Getting more out of your debugger with remote options

Introduction
I bet day to day most people use the built in direct debugger in your IDE. You press a button and everything is done for you. This won't help you if the start up configuration is non trivial, in the case of weblogic for example where you have to run a script, or the process has to run on another machine. In the remote section there are a number of options that are pretty interesting as far as dealing with certain corner cases. I had cause to use some of them recently to track down a particularly hard to reproduce bug and realized that some are actually applicable to day to day work.

All the screen grabs are from JDeveloper; but the concepts should work equally well with other tools.

Normal remote debugging.

JDeveloper at least doesn't come with a remote run profile configured by default but it is really quick to set one up from the project properties dialog. In the Run/Debug/Profile configuration page create a new entry:



Then edit the properties so that JDeveloper knows you are doing remote debugging:



Then you can select this profile to debug:



The first time the debugger runs you will see this connect dialog, for most local debugging work the settings can stay the same so check the box so you don't get asked each time. You might want to consider increasing the timeout a little bit for convenience.


So you need to run your java process with the, erm, simple command line option as follows. Not the easiest to remember string; but I guess "alias" is your friend.
java -agentlib:jdwp=transport=dt_socket,server=y,address=4000 ...

Right so that is the basics, lets try some of the more interesting options.

Start and connect later

In the default mode for the debugger the debuggee process won't start until until the IDE tells it to, and will quit when the debugger stops. This is really annoying if you are trying to debug a remote instance of weblogic server and want to keep it running between sessions. (For example if you configured another server to use instead of the integrated one, I am looking at you Chris Muir) Or if you forget to start the debugger and everything is just sitting there waiting for you to wake up.

So you can use the "suspend=n" flag, this means that the target task will start; but allow you to connect a debugger later:

java -agentlib:jdwp=transport=dt_socket,server=y,address=4000,suspend=n ...

You run the remote debugger in the normal way; but when you "Stop" the debugger you now have a choice to either let the process continue running or to kill it:


This allows you to leave infrastructure running, most like a server, whilst still be able to connect on demand to debug.

Have debugger always running, get the debuggee to connect back

The previous two configurations both require at least two step processes for each debugging session. You have to start the debugger and debuggee. This can be really annoying particularly if you are trying to debug a hard to reproduce problem that requires the target VM to be stopped and started many times.
Luckily there is a setting that allows the debuggee to connect to the debugger at start up. The debugger on the IDE only needs to be started once to listen for events. This takes a bit more to set up so lets start at the IDE end and create a new Run/Debug/Remote entry:



In the properties for "Remote - listener" change to be a JPDA listener rather than the normal attach mode:



Also set the timeout to zero so it listens for-ever and use a different port so that it won't clash with normal debug sessions. (Minor mistake in screen grab, the combobox is showing the wrong value use the value in the previous grab)



Now you just have to run this profile in the normal way, and instead of the debugger starting you should see this listener active in the Run Manager.



So the next step to to run the task you want to debug notice the server flag has changed and we have specified the new port:

java -agentlib:jdwp=transport=dt_socket,address=localhost:5000,server=n ...

In JDeveloper the debugger will start up and then run in the normal way:



You can start multiple sessions at the same time with difference instances of the program you are trying to debug. It can get kind confusing though. It does mean that starting the debuggee is a one step process which seems to save me some vital thinking seconds that I could be applied to the problem in hand.

At some point you may wish to shut down the listener, for completeness you can do this from the run manager:




This is the mode that I am finding a valuable time saver day to day. It might only save a few seconds on each run; but over the last week it has proven to be a real time saver. Of course this is very dependent on just what and how you are debugging on whether you will find this useful.

More details

For more details on the debugging options that a look a this sun Oracle document. There are other options such as in memory transports and starting a debugger on an exception that are worth looking at.

Thursday, April 15, 2010

Forgotten JDeveloper feature : The bytecode debugger

I am pretty lucky in my day to day work that I have access to nearly all of the source code for the software I work with. (Even the close hold Java security code which is very useful when working on the HTTP Analyzer). Sometimes you run across a snippet of code that for whatever reason you don't have the source code to hand. JDeveloper will generate you a stub; but that is not so useful when you want to know what is going on.

There is a kind-of hidden feature in JDeveloper called the bytecode debugger that you can enable by selecting "Show Bytecode":

This will show you the method in question in terms of bytecodes, and you can use the new extra pink toolbar icons to step at the bytecode level or just use the normal ones to step in at the java method level.

Very useful when you are stuck and for very good legal reasons cannot make use of java dissembly tools.

Wednesday, December 2, 2009

Have a job, join us in the JDeveloper WebServices/ Spring/ Weblogic SCA team

We are loosing a valued member of our team to Australia so we are looking to a talented developer to join us in the Reading, UK office. You can find out a little bit more by visiting the jobs page and searching for job 203089.

If you know me and are interested get in touch directly, so I can pass your information on. (Okay and claim the recruitment bonus if we take you :-) )

Thursday, October 22, 2009

Know which class you want but not which library?

This little feature in JDeveloper often goes unnoticed as people assume the search box filters on the library name. In fact it searches all library definitions for classes of the given name:

Don't need it very often; but when you do it is a god send.

Tuesday, October 13, 2009

Taking on the Spring Extension for JDeveloper

Had some interesting news that our team in the UK is taking over the Spring tooling in JDeveloper. There has been for a long while support for Spring tooling provided as an optional extension written by Duncan Mills. This will be the first time that a team has been able to work on it full time.

Of course don't expect to see anything that is the result of this change until a release after R11 PS1*. We would of course be interested to hear any views and opinions on what lovely** new features that related to Spring integration that users would be interested in.

* Standard disclaimer, this statement shouldn't be taken as a promise that we will ship this feature at any point in the future. Nor does it promise we will ever ship another version of JDeveloper.

** The lovelyness of your new feature may down as well as up

Friday, October 9, 2009

Suspend thread in JDeveloper debugger

Just found this little feature whilst working on a narly abbot issue. Basically it allows you to "stop" a thread from executing. This is really useful when debugging threading issues as you can use it to rule out a particular thread as to be the one causing the issue.

It would have been nice if there was a "suspend all other" threads action; but I have logged a bug for this so hopefully there will be one day.

Thursday, October 8, 2009

Project Dogfood, why I am going to spend 20% of my time writing ADF apps

Most of the people working on JDeveloper spend a lot of time writing in Java to support developers who build ADF applications. Unfortunately this doesn't give us developer a lot of daily experience building the sort of application that our customer build day to day using our tools. Particular those of use like myself who work on more general JEE technologies such as web services.

To try and fix this, and hopefully improve the development experience for all of our users, our gov'ner Ted has decreed in the next cycle that every part of of the JDeveloper development team will take time out to build real ADF apps.

To do this 20% of our working week has been set aside in the next development cycle. (The one after next from the customer's point of view) We all have to work in teams to build new and hopefully interesting applications. The parameters of the applications are not defined yet; but we should see some interesting projects coming out of the wood.

This is good news for me of course as it allow me broaden my skills, CometD here I come, and to take some time to escape from web services on day a week. It will be interesting to see how this works with the pressures of releasing production software; but I hope we do get the time as this will be a very interesting experiment. I will let you know how it goes.

Friday, September 4, 2009

Project lombok, interesting bean shortcuts with the annotation processor

I came across a mention of project lombok recently whilst looking for something else. It is a combination of annotations and annotation processors to make bean programming more declarative. For the purposes of this blog I am going to use a quick example using the @Data annotation. So for this simple class the attention of the @Data annotation will at compile time add in getters/settings equals/hashCode and a nice toString implementation.


import lombok.Data;

@Data
public class DataExample {
  
  
   private String name;
   private double score;
   private String tags[];
  
}

Now lombok has integration with Eclipse and javac, since we are using JDeveloper I am stuck with the latter. In theory all you need to do is to make sure that JDeveloper compiles with "javac" with the lombok.jar on your classpath. It turns out that at least in the more recent versions of JDeveloper we use the compiler API directly which doesn't appear to properly invoke the annotation processors in the library. (Look under lombok.jar!/META-INF/services to see how this is wired up) The trick is to configure JDeveloper to run javac "out of process":

Now before you compile JDeveloper might complain that it can't find any of the new methods; but as soon as the classpath is populated even code insight works correctly (although not inside of the DataElement class):

Using the above data you can see how the toString() method is puts together some nice tidy output:

DataExample(name=Bob, score=4.0, tags=[Fun, Tall])

I wonder if the ADF team could use something similar to reduce the amount of boilerplate code that they have to generate. Also with a little bit of work you could get far cleaner JAXB and EJB artifacts. It would also be good if this project was extended to support bound attributes transparently and perhaps create a builder which always takes far too much time in my book.

Wednesday, August 19, 2009

Favourite minor JDeveloper feature, auto highlighting

Following on from Chris' post auto highlight is my favorite minor feature. Just highlights all instances of whatever the cursor is on. Has been available in previous version of jdev as an extension so not that much woo-hoo.

Monday, August 3, 2009

Problem running Jersey on the Integrated Server in JDeveloper on windows

Prior to the latest 1.1.2EA builds you will find that if you deploy Jersey to the integrated weblogic server in JDeveloper on window that you might see a deployment issue due to the fact that the weblogic domain will have a space in its filename. (Think c:\Document and Settings\%USER_NAME%\Application Data\)

This is logged as oracle bug 8752995, this is fixed in the latest builds but there is a workaround and that is to edit ..jdevevloper/jdev/bin/jdev.boot and change the following entry to a path without spaces in it.

ide.user.dir = D:/MyJdev/LocalSettings

Note without the NLS fix in the previous blog entry deployment will fail with a stack trace that looks like this:

com.sun.jersey.api.container.ContainerException: [failed to localize] no.root.res.in.res.cfg()
        at com.sun.jersey.server.impl.application.WebApplicationImpl.processRootResources(WebApplicationImpl.java:718)
        at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:590)
        at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:383)
        at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:377)
        at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:242)

Monday, July 20, 2009

Applying a template to the domain used for the Integrated WebLogic Server

JDeveloper provides you with pre-build install of weblogic and a bunch of useful templates for JRF etc. There are time though when you really need to apply a new template. (For example if you are doing Async web services).

This isn't a problem on windows as the domain is easy to find, $USER_HOME/Application Data/JDeveloper/system.X.X.X.X/DefaultDomain, but on Unix the location is under a "dot" directory, ~/.jdeveloper/system.X.X.X.X/DefaultDomain. This causes a problem for the graphical domain configuration wizard because it wont let you pick a domain that lives in a hidden directory. It also doesn't have a box where you can just type your path which is annoying.

The most obvious workaround is to use the configuration wizard in text only mode which gives you an old fashioned but workable UI. In this interface you can just type the path of the system directory when it asks you where your domains live. Don't fall into the trap I did of giving it the full location of the DefaultDomain, it will prompt you for this on the next page.

If you prefer you can also use wlst for the same work. Just issue a readDomain, then an addTemplate, updateDomain, then a final closeDomain.

Wednesday, July 1, 2009

JDeveloper 11 R1, now up on OTN

A brand spanking new version of JDeveloper to go along with the other R1 components released today. Lots of new features to play with in various components along with a whole bunch of bug fixes.

Friday, May 29, 2009

HATEOAS, REST in the HTTP Analyzer in JDeveloper

I have been working on adding some REST support to JDeveloper back in the labs. In particular I have been focusing on support for HATEOAS in the HTTP Analyzer. I put together a quick viewlet that demonstrates the basic features to get some early feedback.

I cannot say if or when these features will ever see the light of day as per the standard Oracle SOP so please take this into consideration when watching the viewlet.

Update: I noticed that in the demo the create method returns 303, it should proper return "201 Created" to be correct.

Thursday, March 5, 2009

JDeveloper code editor "rabbit in a hat" magic trick

Sometimes it is not the bug itself; but how you report them that gets the smile. Take for example this test case for a bug in JDeveloper provided by fellow web service team member Alan Davis.

Create a new java file called Class1 and paste in the following text.

package project1

public class Class1
{
   public void method()
   {
     /** */
     class Foo extends ArrayList
     {
         /*
          *          /| |\
          *         | |_| |
          *         | |_| |          And for my next trick,
          *         | . . |          not only will I make the
          *         \  @  /          rabbit disappear, but
          *       ===========        I will make the hat
          *       |_       _|        vanish too...
          *         |      |
          *         |      |
          *         |______|
          */
     };
   
     doIt(); // Comment
   }
   void doIt() {}
}

Then accept the import assistance on the ArrayList import. Ta-daa. For weeks Alan was wondering why we kept on deleting his code... now we know it was just a magic trick. Fortunately you need a very specific combination of code structures and comments to exercise this bug so you shouldn't see this using 11 day to day.

Thursday, February 19, 2009

Exposing Tables Mapped to Entity Beans as a Webservice

I wanted to create a simple web service to access some database tables. This turns out to be a little bit harder than I though as the classes generated for JPA are a little bit different in intention as those required JAXB / Web Services which are more method driven. This example just uses EJB; but the same should apply to using JPA straight.

Although the screen grabs are from JDeveloper, of course, the the following should apply to most java IDEs. So first of all lets create some entities from tables in the database:

Then I am going to create a connection to the old favourite scott/tiger:

Now in the screen shot and a few more I have selected more than just Emp/Dept. Just ignore that and assume that I had just selected the two. I didn't have the heart to go back and re-shoot them.

So finish the entity bean wizard and then bring up the EJB Sesssion Bean wizard so we can create a suitable Façade to publish as our web service.

You can pretty much accept the defaults on this page as it has already picked up the persistence unit from the previous wizard:

Now we can just clagg on the @WebService annotation and run the service....

... well it turns out that if you try to run the Session Bean that it fails to deploy to the server with something like the following error:


[HTTP:101216]Servlet: "WSEE_SERVLET" failed to preload on startup in Web application: "/EmpDept-EmpDeptFacade-webapp".
javax.xml.ws.WebServiceException: Unable to create JAXBContext
 at com.sun.xml.ws.model.AbstractSEIModelImpl.createJAXBContext(AbstractSEIModelImpl.java:158)
 ...
 at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
Caused by: java.security.PrivilegedActionException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.sql.Timestamp does not have a no-arg default constructor.
 this problem is related to the following location:
  at java.sql.Timestamp
  at public java.sql.Timestamp empdeptfacade.Emp.getHiredate()
  at empdeptfacade.Emp
  at public java.util.List empdeptfacade.jaxws.QueryEmpFindAllResponse._return
  at empdeptfacade.jaxws.QueryEmpFindAllResponse

 at java.security.AccessController.doPrivileged(Native Method)
 at com.sun.xml.ws.model.AbstractSEIModelImpl.createJAXBContext(AbstractSEIModelImpl.java:148)
 ... 54 more
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.sql.Timestamp does not have a no-arg default constructor.
 this problem is related to the following location:
  at java.sql.Timestamp
  at public java.sql.Timestamp empdeptfacade.Emp.getHiredate()
  at empdeptfacade.Emp
  at public java.util.List empdeptfacade.jaxws.QueryEmpFindAllResponse._return
  at empdeptfacade.jaxws.QueryEmpFindAllResponse

 at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:102)
 at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:438)
 at com.sun.xml.bind.v2.runtime.JAXBContextImpl.(JAXBContextImpl.java:286)
 at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:139)
 at com.sun.xml.bind.api.JAXBRIContext.newInstance(JAXBRIContext.java:105)
 at com.sun.xml.ws.model.AbstractSEIModelImpl$1.run(AbstractSEIModelImpl.java:153)
 at com.sun.xml.ws.model.AbstractSEIModelImpl$1.run(AbstractSEIModelImpl.java:148)
 ... 56 more

Now JAXB will handle quite a few cases/classes by default; but one annoying case it won't deal with is the java.sql.Timestamp class as it doesn't have a no-arg constructor. So work around this you need to define an adapter to do the conversion, here is a trivial implementation that may not work in all cases, particularly is you plan to write back to the database:

package empdeptfacade;

import java.sql.Timestamp;

import java.util.Date;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class TimestampAdapter
  extends XmlAdapter<Date, Timestamp> {

    public Date marshal(Timestamp v) {
        return new Date(v.getTime());
    }

    public Timestamp unmarshal(Date v) {
        return new Timestamp(
            v.getTime());
    }
}

Now you could attach this to each and every usage of the Timestamp class, admittedly just the once in this case, but a much tidier way to do it is to attach it to the package-info.java class instead and have it apply to a number of classes. Unfortunately JDeveloper doesn't allow you to create one from the java wizard - so you just have to use the "New File" wizard from the gallery.

And the code for the package needs to look like:


@XmlJavaTypeAdapters(
   @XmlJavaTypeAdapter(value=TimestampAdapter.class,type=Timestamp.class))
package empdeptfacade;

import java.sql.Timestamp;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

You should now find that your EJB will deploy quite happily; but you will find that if you actually invoke one of the methods on the web service it fails with the following error:

avax.xml.ws.WebServiceException: javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: empdeptfacade.Dept@50dd8d -> empdeptfacade.Emp@11541d8 -> empdeptfacade.Dept@50dd8d]
 at com.sun.xml.ws.message.jaxb.JAXBMessage.writePayloadTo(JAXBMessage.java:322)
 at com.sun.xml.ws.message.AbstractMessageImpl.writeTo(AbstractMessageImpl.java:153)
 at com.sun.xml.ws.encoding.StreamSOAPCodec.encode(StreamSOAPCodec.java:108)
 at com.sun.xml.ws.encoding.SOAPBindingCodec.encode(SOAPBindingCodec.java:258)
 at com.sun.xml.ws.transport.http.HttpAdapter.encodePacket(HttpAdapter.java:326)
 at com.sun.xml.ws.transport.http.HttpAdapter.access$100(HttpAdapter.java:99)
 at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:460)
 at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:250)
 at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:140)
 at weblogic.wsee.jaxws.HttpServletAdapter$AuthorizedInvoke.run(HttpServletAdapter.java:289)
 at weblogic.wsee.jaxws.HttpServletAdapter.post(HttpServletAdapter.java:202)
 at weblogic.wsee.jaxws.JAXWSServlet.doPost(JAXWSServlet.java:237)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
 at weblogic.wsee.jaxws.JAXWSServlet.service(JAXWSServlet.java:77)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
 at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
 at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
 at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3586)
 at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
 at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
 at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2196)
 at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2102)
 at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1428)
 at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
 at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: empdeptfacade.Dept@50dd8d -> empdeptfacade.Emp@11541d8 -> empdeptfacade.Dept@50dd8d]
 at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:282)
 at com.sun.xml.bind.v2.runtime.BridgeImpl.marshal(BridgeImpl.java:90)
 at com.sun.xml.bind.api.Bridge.marshal(Bridge.java:107)
 at com.sun.xml.ws.message.jaxb.JAXBMessage.writePayloadTo(JAXBMessage.java:317)
 ... 26 more
Caused by: com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: empdeptfacade.Dept@50dd8d -> empdeptfacade.Emp@11541d8 -> empdeptfacade.Dept@50dd8d
 at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:244)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.pushObject(XMLSerializer.java:533)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:627)
 at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
 at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
 at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
 at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
 at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:152)
 at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
 at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
 at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
 at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:152)
 at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
 at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
 at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:277)
 ... 29 more

Problem here is the methods it generates are a bit too helpful. For example Dept has a method that returns all of the Employees in the Department which in turn returns the Department you are in. Now there are a variety of ways you can solve this problem but I am going for the simplest method of marking the employee accessors of Dept as transient.

You can now run the service and get a list of departments back:

Now the Emp class has a similar problem in that for each Emp you get a copy of the Dept for it. This denormlizes the data and might be a problem in certain use cases. You can consider using XMLID/XMLIDref as mentioned in the previous link but this will only work properly if you return a structure that contains the employees and the department. Otherwise you will not get any department objects back to the client. You would need to make the following changes to get this to work:


// Changes to Dept.java note XmlID has to be of type String
// otherwise JAXB will complain.

    @XmlID
    @XmlJavaTypeAdapter(LongAdapter.class)
    public Long getDeptno() {
        return deptno;
    }

// Changes to Empt.java

    @XmlIDREF
    public Dept getDept() {
        return dept;
    }

// Long Adapter

public class LongAdapter extends XmlAdapter<String, Long> {


    public Long unmarshal(String v) {
        return Long.parseLong(v);
    }

    public String marshal(Long v) {
        return v.toString();
    }
}

// Extra query method in SessionEJBBean

    public EmpDeptList queryEmpFindAllWithDepts() {
        List<Emp> list = em.createNamedQuery("Emp.findAll").getResultList();
        Set<Dept> deps = new HashSet<Dept>();
        for (Emp emp : list) {
            deps.add(emp.getDept());
        }
        
        EmpDeptList edl = new EmpDeptList();
        edl.setEmployees(list);
        edl.setDepartments(deps);
        return edl;
    }

The cool thing about JAX-B is that on the client side the object are linked back together even though in the XML message they are sent as two different lists. (Note the cast in Dept, not sure if this is a bug or a feature of using IDRef. Something to look into at a future date)

    sessionEJBBeanService = new SessionEJBBeanService();
    SessionEJBBean sessionEJBBean = sessionEJBBeanService.getSessionEJBBeanPort();
    // Add your code to call the desired methods.

    QueryEmpFindAllWithDeptsResponse allWithDepts =
        sessionEJBBean.queryEmpFindAllWithDepts(new QueryEmpFindAllWithDepts());
    Emp e = allWithDepts.getReturn().getEmployees().get(0);
    Dept d = (Dept)e.getDept();
    System.out.println(d.getDname());

Of course this exposes the limitation of the annotation programming model as it is much harder to present different XML views of your data depending with the same bean model. The key take away point I guess is that database data can be in the form or a mesh whereas you have to be careful when creating web services and generating XML that the data is mapped into a tree.

Thursday, February 5, 2009

Configuring JDeveloper to use a different install | domain of weblogic

One of the cool features in JDeveloper that only gets used now and then is the ability to configure JDeveloper to use a different install of weblogic when running internally. It could also be the case you need a custom configured Domain to support your application, for example when doing buffered web services.

To configure a server connection you need to go to Tools -> Preferences -> Run then Edit Server instances.

We are going to create a new configuration, so press the New button and you should see a screen as follows (you could of course just edit the default server configuration and this would affect the entire IDE rather than on a application by application basis):

Now by default JDeveloper assumes that you are try to connect to a remote weblogic instance. So you could just define a new connection to this server, big green plus top right, and you would be ready to go at this point. For the purposes of this blog we are going to assume that you want to let JDeveloper do the management of a server on the current machine. So we tick "Let JDeveloper manage...." and provide the location of the wls_server and where the domain in placed. You do still need to create a valid connection to where the server will start up to; but you obviously wont be able to test this server connection until after you have let JDeveloper start the instance.

The final step is to configure the listener port, in most cases you should just set this to what is configured in your domain:

So you can now assign this application server instance to a particular application in jdeveloper. First bring up the properties for the application:

Then select the custom configuration that we created before. Note you can create new configurations here also; but I showed the preferences way of doing things for completeness.

Now anything you Run/Debug/Profile/Test from inside of this application will use this server instance.