Tuesday, March 19, 2013

Using Axis2 as JAX-WS Web Service Provider using RAD/Eclipse with Maven



This blog is a little rough... it's more like a journal entry or log of steps I went through trying to use Axis2 to provide a JAX-WS web service.  I actually used IBM's RAD (Rational Application Developer) which is IBM's flavor of Eclipse to do generate the JAX-WS code; however, I then used Axis2 as the web service engine when deploying to Websphere Application Server 6.1.

But hopefully this will be useful to someone, even if they aren't deploying to WAS, but just want an example of how to package Axis2 with their web app or want to see how to use Maven to create the servicejars.    As you'll see, I started with Axis2 1.5 and ran into issues and went back to 1.4 to get things working, but later I updated to 1.6 (when it came out) and things went fine.  So, I'd start with the latest version of Axis2 if possible.

Here's the blow by blow of the steps invovled:


  1. Create an Web Project and Ear
  2. Copy Axis2 jars and such from Axis2 war to web project




  1. Also copy the axis2_web folder into your Webcontent or webapp folder


  1. Change deployment descriptor




  1. Tried publishing to server but got this:

[1/8/10 16:32:15:224 EST] 0000001d SystemErr     R com.ibm.ws.metadata.annotations.AnnotationException: Annotation processing failed for class:  com/ibm/icu/impl/data/LocaleElements_zh__PINYIN.class
[1/8/10 16:32:15:224 EST] 0000001d SystemErr     R at com.ibm.ws.metadata.annotations.AnnotationConfigReader.getAnnotationData(AnnotationConfigReader.java:461)



  1. Remove icu4j-2.6.1.jar from WEB-INF/lib.


  1. Re-publish/Re-start the server and your Axis2 install should be ready to go.


  1. You can verify your Axis2 installation, but running the index.jsp under the WebContent/axis2-web folder.



  1. Then from the Axis2 Welcome page go to the “Validate” link, which will take you to the Axis2 Happiness Page.  Everything should be happy.



  1. Then create a generic project for the WSDL and Schema.


  1. Create a Dynamic Web Project to hold the generated service code.  It has to be a web project only because of the IBM wizard.  We will actually jar it up later and package it under the other web project.  (We actually don’t want this project associated with the EAR, but the wizard will make it associated anyway… So, we will have to undo this..






  1. Now run the Web Service wizard…Right click on the WSDL (from the package Explorer or Project Explorer) and go to Web Services->



  1. Change the Web Service Runtime to JAX-WS.  And select your newly created web project as the Service Project.



  1. On the next screen, I left the defaults:




  1. Click finish.  I got an error because it tried to deploy to my server which does not have the Web Services feature pack.  This is fine because I will be using Axis2 as my JAX-WS runtime and not Websphere’s implementation which comes with the feature pack.




  1. This generated the classes based on the schema and created a service class for us called “StandardizePlaceImpl”.





  1. Modified the StandardizePlaceImpl to return a response based on the input.
  2. Remove the project with the generated code from the EAR’s application XML:



  1. Create a folder in the WEB-INF folder of your Axis2 web project to hold the JAX-WS web service.




  1. JAR up your code and put the WSDL and the schema in the META-INF  folder in the jar.  Used the following pom file to jar up the code and this attempt does not include the WSDL’s and schemas.

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nw.gis</groupId>
<name>gis web service</name>
<artifactId>gis-ws</artifactId>
<version>1.0</version>
<packaging>jar</packaging>

<properties>
<sourceComplianceLevel>1.5</sourceComplianceLevel>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<inherited>true</inherited>
<configuration>
<source>${sourceComplianceLevel}</source>
<target>${sourceComplianceLevel}</target>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ws-metadata_2.0_spec</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jaxws_2.1_spec</artifactId>
<version>1.0</version>
</dependency>
</dependencies>


</project>



  1. Now move the created jar into the servicejars folders under the axis2 folder.



  1. Now refresh the web project and then re-publish and restart the server.

[1/12/10 9:49:25:353 EST] 00000021 ServiceDeploy I org.apache.axis2.deployment.ServiceDeployer deploy Deploying Web service: version-1.5.1.aar - file:/C:/WorkSpaces/RAD7/Axis2_JAXWS/gis-axis-jaxws-ws/WebContent/WEB-INF/services/version-1.5.1.aar
[1/12/10 9:49:25:353 EST] 00000021 JAXWSDeployer I org.apache.axis2.jaxws.framework.JAXWSDeployer deploy Deploying artifact : gis-ws-1.0.jar
[1/12/10 9:49:25:462 EST] 00000021 JAXWSDeployer I org.apache.axis2.jaxws.framework.JAXWSDeployer deployClasses Deploying JAXWS annotated class com.nationwide.gis.service.standardizeplace_1.StandardizePlaceImpl as a service - StandardizePlace.StandardizePlace
[1/12/10 9:49:25:571 EST] 00000021 ServletWrappe I   SRVE0242I: [gis-axis-jaxws-ear] [/gis-axis-jaxws-ws] [AxisServlet]: Initialization successful.



  1. Go back the Axis2 index.jsp and then click Services.



  1. When I click on the service name, which usually shows you the WSDL, I get this error:


<error>
  <description>Unable to generate WSDL 1.1 for this service</description>
  <reason>If you wish Axis2 to automatically generate the WSDL 1.1, then please set useOriginalwsdl as false in your services.xml</reason>
  javax.xml.ws.WebServiceException: Error occurred generating WSDL file for Web service implementation class {com.nationwide.gis.service.standardizeplace_1.StandardizePlaceImpl}: {java.lang.Exception: Error occurred while attempting to read generated schema file {java.lang.RuntimeException: java.net.URISyntaxException: Illegal character in path at index 16: file:/C:/Program Files/IBM/SDP70/runtimes/base_v61/profiles/Axis2JaxWS/temp/NW917514Node10/server1/gis-axis-jaxws-ear/gis-axis-jaxws-ws.war/_axis2com.nationwide.gis.service.standardizeplace_1.StandardizePlaceImpl/StandardizePlace_schema3.xsd}} at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.generateWsdl(JAXWSRIWSDLGenerator.java:187) at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.initialize(JAXWSRIWSDLGenerator.java:371) at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.getWSDL(JAXWSRIWSDLGenerator.java:364) at org.apache.axis2.description.AxisService.printWSDL(AxisService.java:1314) at org.apache.axis2.transport.http.ListingAgent.processListService(ListingAgent.java:270) at org.apache.axis2.transport.http.AxisServlet.doGet(AxisServlet.java:249) at javax.servlet.http.HttpServlet.service(HttpServlet.java:743) at javax.servlet.http.HttpServlet.service(HttpServlet.java:856) at



  1. When I use SOAP UI and point it to a local copy of the WSDL and invoke the service I get this:
1/12/10 11:05:25:080 EST] 00000020 FactoryRegist E org.apache.axis2.jaxws.registry.FactoryRegistry <clinit> null
                                java.lang.ExceptionInInitializerError
at java.lang.J9VMInternals.initialize(J9VMInternals.java:214)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:258)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:139)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:117)
Caused by: java.lang.ClassCastException: org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl incompatible with javax.xml.datatype.DatatypeFactory
at javax.xml.datatype.DatatypeFactory.newInstance(Unknown Source)
at com.sun.xml.bind.DatatypeConverterImpl.<clinit>(DatatypeConverterImpl.java:783)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:192)
... 47 more


  1. Noticed that the class it was complaining about was in the xercesImpl-2.8.1.jar which comes with Axis2 1.4, but my Axis2 1.5 version came with an older version of xercesImpl-2.6.2.jar.  So, I replaced my xerces jar with the newer version.  I believe it was using an implementation from IBM and not from the Axis2 jars since there was no implmentation in the Axis libs.


  1. After this change it worked fine for the first request submitted, but then I got an error on any more requests that I submitted:


[1/12/10 13:53:21:080 EST] 0000001d AxisEngine    E org.apache.axis2.engine.AxisEngine receive javax.xml.bind.UnmarshalException
- with linked exception:
[javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.nationwide.com/schemas/iaa7_1/customerrelationmanagement/GIS/placeInformationManagement_1", local:"standardizePlace"). Expected elements are (none)]
                                org.apache.axis2.AxisFault: javax.xml.bind.UnmarshalException
- with linked exception:
[javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.nationwide.com/schemas/iaa7_1/customerrelationmanagement/GIS/placeInformationManagement_1", local:"standardizePlace"). Expected elements are (none)]
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430)
at org.apache.axis2.jaxws.server.JAXWSMessageReceiver.receive(JAXWSMessageReceiver.java:218)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:173)
...
Caused by: javax.xml.ws.WebServiceException: javax.xml.bind.UnmarshalException
- with linked exception:
[javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.nationwide.com/schemas/iaa7_1/customerrelationmanagement/GIS/placeInformationManagement_1", local:"standardizePlace"). Expected elements are (none)]
at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactor
... 25 more


  1. Let’s see if we can turn on any logging using Log4J.  So, I added a commons-logging.properties file to the classpath with the following lines:

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
priority=999


  1. Then I added a log4j.properties file, and turned on debug level logging on the root logger.


  1. Re-ran the test… Got this for the second request which errored out… (note second request is same as first):

[1/12/10 15:10:25:795 EST] 00000020 SystemOut     O [01/12/2010 15:10:25,795]JAXBUtils DEBUG: This classloader will be used to construct the JAXBContext
com.ibm.ws.classloader.CompoundClassLoader@34043404
  Local ClassPath: C:\WorkSpaces\RAD7\Axis2_JAXWS\gis-axis-jaxws-ws\WebContent\WEB-INF\classes;C:\WorkSpaces\RAD7\Axis2_JAXWS\gis-axis-jaxws-ws\WebContent\WEB-INF\lib\activation-1.1.jar;C:\WorkSpaces\RAD7\Axis2_JAXWS\gis-axis-jaxws-ws\WebContent\WEB-INF\lib\antlr-2.7.7.jar;C:\WorkSpaces\RAD7\Axis2_JAXWS\gis-axis-jaxws-ws\WebContent\WEB-...
<removed cause it was really long>
[1/12/10 15:10:25:795 EST] 00000020 SystemOut     O [01/12/2010 15:10:25,795]JAXBUtils DEBUG: checking package :com.nationwide.schemas.iaa7_1.customerrelationmanagement.gis.placeinformationmanagement_1
[1/12/10 15:10:25:795 EST] 00000020 SystemOut     O [01/12/2010 15:10:25,795]JAXBUtils DEBUG: Exception thrown from AccessController: java.security.PrivilegedActionException: java.lang.ClassNotFoundException: com.nationwide.schemas.iaa7_1.customerrelationmanagement.gis.placeinformationmanagement_1.ObjectFactory
[1/12/10 15:10:25:795 EST] 00000020 SystemOut     O [01/12/2010 15:10:25,795]JAXBUtils DEBUG: ObjectFactory Class Not Found java.lang.ClassNotFoundException: com.nationwide.schemas.iaa7_1.customerrelationmanagement.gis.placeinformationmanagement_1.ObjectFactory
[1/12/10 15:10:25:795 EST] 00000020 SystemOut     O [01/12/2010 15:10:25,795]JAXBUtils DEBUG: Exception thrown from AccessController: java.security.PrivilegedActionException: java.lang.ClassNotFoundException: com.nationwide.schemas.iaa7_1.customerrelationmanagement.gis.placeinformationmanagement_1.package-info
[1/12/10 15:10:25:795 EST] 00000020 SystemOut     O [01/12/2010 15:10:25,795]JAXBUtils DEBUG: package-info Class Not Found java.lang.ClassNotFoundException: com.nationwide.schemas.iaa7_1.customerrelationmanagement.gis.placeinformationmanagement_1.package-info
[1/12/10 15:10:25:795 EST] 00000020 SystemOut     O [01/12/2010 15:10:25,795]JAXBUtils DEBUG: Package com.nationwide.schemas.iaa7_1.customerrelationmanagement.gis.placeinformationmanagement_1 does not contain an ObjectFactory or package-info class.  Searching for JAXB classes
[1/12/10 15:10:25:795 EST] 00000020 SystemOut     O [01/12/2010 15:10:25,795]JAXBUtils DEBUG: getClassesFromJarFile failed to get Classes


  1. Replaced all Axis2 1.5 jars and folders under WEB-INF with Axis2 1.4 versions and the service works… I have issues getting Axis2 to display the WSDL, but invoking the service works just fine.


  1. I get the following error when trying to click on the Service name to see the WSDL…

[2/15/10 12:07:08:217 EST] 00000020 SystemOut     O [02/15/2010 12:07:08,217]JAXWSRIWSDLGenerator ERROR: Error occurred generating WSDL file for Web service implementation class {com.nationwide.gis.service.standardizeplace_1.StandardizePlaceImpl}: {java.lang.reflect.InvocationTargetException}
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:615)
at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.generateWsdl(JAXWSRIWSDLGenerator.java:173)
at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.initialize(JAXWSRIWSDLGenerator.java:371)
at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.getWSDL(JAXWSRIWSDLGenerator.java:364)
at org.apache.axis2.description.AxisService.printWSDL(AxisService.java:1322)
at ...
Caused by: java.lang.ExceptionInInitializerError
at java.lang.J9VMInternals.initialize(J9VMInternals.java:214)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:219)
at ...
... 33 more
Caused by: java.lang.ClassCastException: org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl incompatible with javax.xml.datatype.DatatypeFactory
at javax.xml.datatype.DatatypeFactory.newInstance(Unknown Source)
at com.sun.xml.bind.DatatypeConverterImpl.<clinit>(DatatypeConverterImpl.java:740)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:192)



UPDATE: 03/23/2012:

Did some more testing with this approach again, and found that I could follow most of this document and get a web service working with RAD 8 and Axis2 1.6.0.

I generated the code in RAD using the WSDL and JAX-WS.  Then created a Dynamic Web Project that I then copied the Axis2 stuff into… all but the libs.  We should be using maven to populate the libs (or m2Eclipse plugin).  I had Axis2 1.6.0 added to our internal enterprise repo last year and found that for most JAX-WS services you just need to add the following dependencies:

<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-kernel</artifactId>
<version>${axis2Version}</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.neethi</groupId>
<artifactId>neethi</artifactId>
</exclusion>

</exclusions>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-http</artifactId>
<version>${axis2Version}</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-local</artifactId>
<version>${axis2Version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-adb</artifactId>
<version>${axis2Version}</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-jaxws</artifactId>
<version>${axis2Version}</version>
</dependency>
<dependency>
<groupId>org.apache.neethi</groupId>
<artifactId>neethi</artifactId>
<version>2.0.5</version>
</dependency>


This should pull in the jars necessary to use JAX-WS with Axis2.

Also, I used the following plugin configuration in the WAR pom to pull in the generated code into the WEB-INF/servicejars folder.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
  <!-- this is relative to the pom.xml directory -->
      <directory>../spell-check-ws-gen/target</directory>
      <targetPath>WEB-INF/servicejars</targetPath>
      <includes>
    <include>spell-check-ws-gen*</include>
  </includes>
    </resource>
</webResources>
</configuration>
</plugin>


The “spell-check-ws-gen” project is where I had the generated JAX-WS code.  This plug-in configuration was in the Dynamic Web Project that I created and copied the Axis2 stuff into (stuff = web.xml, axis2-web, servicejars folder, modules, etc… but not the lib)

As long as my spell-check-ws-gen project was one of the modules referred to by the build project’s pom, then it would get built and then when the war project got built this plugin would run and pull that jar into the servicejars folder where Axis2 expects it.

At first I put the JAX-WS generated code jar only in the servicejars folder, but then I would get this error:

AxisEngine    E org.apache.axis2.engine.AxisEngine receive org.apache.axis2.jaxws.wrapper.impl.JAXBWrapperException: java.lang.IllegalArgumentException: argument type mismatch
                                org.apache.axis2.AxisFault: org.apache.axis2.jaxws.wrapper.impl.JAXBWrapperException: java.lang.IllegalArgumentException: argument type mismatch


I found that if I added the jar with the generated JAX-WS code(that is the spell-check-ws-gen in my case) also to the WEB-INF/lib, then this error would go away.

So, this jar would be in two places… in the WEB-INF/lib folder and in the WEB-INF/servicejars folder.  Then the service would work fine.

The Axis2 services page was not be able to produce a wsdl for the service, but I didn’t care.

No comments:

Post a Comment