Wednesday, August 10, 2011

Expose your Session Bean as a Web Service with JAX-WS and Eclipselink

In this blogpost I will show you how you can expose your EJB Session Bean as a Web Service, also tell you everything what I encountered and how I solved my issues. I will do this in JDeveloper and I will use the following frameworks: Eclipselink, JAX-WS and test it on WebLogic.

First let's start with the JPA part. In my project I generated some entities based on the Emp & Dept tables of the Scott schema.

In this demo I want to retrieve one department so I need to add a NamedQuery. I added Dept.findByPK to the NamedQueries annotation. Normally you only need to add the following JQL statement select o from Dept o where o.deptno = :deptid 
In this case I didn't want to set the OneToMany relation between Emp and Dept to eager. This can cause a fetch loop, so let's use the default value ( lazy ). I still need to fetch the employees on a department so I can return the department with all its employees in the Web Service response. To also fetch the employees I can add join fetch o.empList to the JQL statement.  

The Emp entity also got some important adjustments.
This entity got an attribute called hiredate with  timestamp as java type. First I added the Temporal annotation with a Date value and also change the java type to Calendar else it will be ignored by the Web Service.
Because this entity has a getter to the Dept entity and Dept got one to Emp we need to break the loop for the Web Service response. You can do this by adding the XmlTransient annotation to the getDept() method. Else you will get an empty response or this error Premature end of file encountered

This is my Session Bean where I added the WebService, WebMethod and WebParam annotation to the session bean to control the WSDL.

When you change one of these annotations you can get an deployment compiler error  like

weblogic.utils.AssertionError: ***** ASSERTION FAILED ***** Caused by: java.lang.ClassNotFoundException:
at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(

To fix this you need to remove the EJBCompilerCache folder located in MiddlewareJDevPS5\jdeveloper\system11.\DefaultDomain\servers\DefaultServer\cache

Also in Eclipselink I used getResultList() and return a list instead of using GetSingleResult(). With GetSingleResult you get an error when there is no result. So you need to handle that when you use it.
At last we can also remove the Web Service annotations from the Session Bean, create a new class and maybe do Contract first . ( this will fix the EJBcompiler errors and keeps it more clean.) In this class I inject the Session Bean to a private variable and call it's ejb methods.
Now you can run it and test the EJB Web Service.

1 comment: