Learning Apache CXF with Eclipse and soapUI plugin

I must admit it went very smoothly and I could finally use the tools I’ve been hearing here and there all the time. I can’t however say it was for Apache CXF’s simplicity itself or just by a stroke of luck, but eventually the puzzles fit together really well.

While working on the upgrade to Apache CXF 2.3.3 in Apache OpenEJB 4, I ran across the following exception.

java.lang.NoClassDefFoundError: org/springframework/core/NestedRuntimeException
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:169)
	at org.apache.cxf.common.util.SpringAopClassHelper.<init>(SpringAopClassHelper.java:30)
	at org.apache.cxf.common.util.ClassHelper.<clinit>(ClassHelper.java:30)
	at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:139)
	at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:183)
	at org.apache.openejb.server.cxf.CxfEndpoint.doPublish(CxfEndpoint.java:192)
	at org.apache.openejb.server.cxf.CxfEndpoint.publish(CxfEndpoint.java:153)
	at org.apache.openejb.server.cxf.CxfWsContainer.start(CxfWsContainer.java:56)
	at org.apache.openejb.server.cxf.ejb.EjbWsContainer.start(EjbWsContainer.java:40)
	at org.apache.openejb.server.cxf.CxfService.createEjbWsContainer(CxfService.java:51)
 

Notice the

org.apache.cxf.jaxws.JaxWsServerFactoryBean.create()

method in the stack trace. That’s what caught my attention and reminded about the idea of Apache CXF self-learning.

The javadoc of org.apache.cxf.jaxws.JaxWsServerFactoryBean was accompanied with the example which greatly helped getting the gist of the class’ intent.

I quickly fired up Eclipse, created a Java project, added Maven dependency support (with the help of m2eclipse plugin) and added

org.apache.cxf:cxf-bundle:2.3.3

as a dependency. I was pleasantly surprised how easy it was to add a dependency with all its own further dependencies with the m2eclipse plugin so I didn’t have to do it myself.

package pl.jaceklaskowski.cxf;

import javax.jws.WebService;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

public class JaxWsServerFactoryBeanTest {

    public static void main(String[] args) {
        JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
        sf.setServiceClass(MyService.class);
        sf.setAddress("http://localhost:9000/test");
        sf.create();
    }

    @WebService
    static class MyService {
        public int add(int x, int y) {
            return x + y;
        }
    }
}

The key was the class, called the service class in CXF, with

@WebService

annotation. That’s the JAX-WS Web Service. I ran the class and used the specified JAX-WS endpoint at http://localhost:9000/test. It didn’t work – whenever I executed the service I received a fault.

I pulled down the sources of CXF and had a look at the

rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/JaxWsServerFactoryBeanTest.java

test class that revealed some of its possible uses.

An observation: What might not be obvious at the first sight is the class name and its methods – org.apache.cxf.jaxws.JaxWsServerFactoryBean – they seem to be built according to the rules of Spring Framework IoC framework where classes are named with the “Bean” postfix, the state is mutated with a bunch of setters and there’s a single “create” method to instantiate an object of the class. It’s helpful when XMLize its configuration with Spring IoC.

That was when I turned my attention to soapUI for Web Service testing. I kept hearing good opinions about the tool and had recently heard about its integration with Eclipse.

Installing the soupUI plugin for Eclipse requires pointing the Eclipse Updater to

http://www.soapui.org/eclipse/update

, run it through a few steps and restarting Eclipse.

I wish it had been as easy as firing up Eclipse Marketplace and entering soapui in the Find field of the Search tab.

It might have been, but I could not find it.

I opened Show View and fire up soapUI Navigator.

There’s even a dedicated perspective for soapUI.

I created a new soapUI project with the WSDL URL.

I ran the project and received a bizarre fault:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>Could not access service object.</faultstring>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

with the following error message in the logs:

Caused by: java.lang.IllegalAccessException: Class org.apache.cxf.service.invoker.PerRequestFactory can not access a member of class pl.jaceklaskowski.cxf.JaxWsServerFactoryBeanTest$MyService with modifiers ""
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
	at java.lang.Class.newInstance0(Class.java:349)
	at java.lang.Class.newInstance(Class.java:308)
	at org.apache.cxf.service.invoker.PerRequestFactory.create(PerRequestFactory.java:55)
	... 31 more

It turned out I needed the

public

qualifier for the service class

JaxWsServerFactoryBeanTest.MyService

!

package pl.jaceklaskowski.cxf;

import javax.jws.WebService;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

public class JaxWsServerFactoryBeanTest {

    public static void main(String[] args) {
        JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
        sf.setServiceClass(MyService.class);
        sf.setAddress("http://localhost:9000/test");
        sf.create();
    }

    @WebService
    public static class MyService {
        public int add(int x, int y) {
            return x + y;
        }
    }
}

After the change it worked like a charm.

It even worked with the browser of mine alone.

That made my day. I seem to like working with Apache CXF.

Be Sociable, Share!
This entry was posted in Frameworks.

2 Responses to Learning Apache CXF with Eclipse and soapUI plugin

  1. ragnor says:

    Typo in Apache CXF version, should be 2.3.3 not 3.3.2.

Leave a Reply

%d bloggers like this: