Thursday, March 25, 2010

Maven JAXWS pulgin for web services

Developing a WebService and Client has been made real simple with JAX-WS technology as part of Jee1.5 specification.

In JAX-RPC the service and clients have to have proxies (Skeletons at service and Stubs at client) to establish the communication, because Bindings and parsings are proproitery and deployment descriptors are required during execution/runtim.

Since JDK1.5 has come up with annotations that enable JEE5.0 to arrive with new feature (a dynamic proxy generation) during execution time which eliminated stubs, skeletons generation and deployment descriptors.

The Dynamic Proxy client is dynamically generated at run time using the Java 5 Dynamic Proxy functionality, while the JAX-RPC-based stub client is a non-portable Java file that is generated by tooling. Unlike the JAX-RPC stub clients, the Dynamic Proxy client does not require you to regenerate a stub prior to running the client on an application server for a different vendor because the generated interface does not require the specific vendor information.

To minimize the developer effort to create webservice and client, I've created a sample maven-archetype that uses jaxws-maven-plugin from org.apache.maven.plugins. The archetype creates a sample webservice (AppWS) with one method  (sayHello) and client (AppWSClient) to access the service.

Junit test cases are also provided to prove service and clients and tested are successfully.

Please follow below steps to feel the webservice and client creation using JAX-WS.


Assumptions: Any IDE (I've used NetBean6.8) is preferred that allows to develop JEE1.5 applications on Maven, ANT and any JEE 5 server (Ex. Glassfish V2 orV3 or WAS7.0 and WAS6.1 with JAXWS enabled).


1. Download and extract mycompany-archetype-j2ee1.5-jaxws.rar into local machine
2. Run mvn (assuming Maven 2.x is installed)
3. Notice mycompany-archetype-j2ee1.5-jaxws-1.0.jar created in local maven2 repository (Ex. USERHOME/.m2\repository\org\mycompany\archetypes\mycompany-archetype-j2ee1.5-jaxws\1.0 )
4. Add this new archetype to USERHOME/.m2/archetype-catalog.xml)

 <archetype>
   <groupId>org.mycompany.archetypes</groupId>
   <artifactId>mycompany-archetype-j2ee1.5-jaxws</artifactId>
   <version>1.0</version>
   <description>mycompany-archetype-j2ee1.5-jaxws</description>
</archetype>
 
Creating a Project from mycompany-archetype-j2ee1.5-jaxws(1.0)
5. Create a new project (ex. jaxwsSample1) from this archetype


 

 6. Click on 'Next' button to select this archetype

 
7. Click on 'Next' button provide project and maven coordinates.

 







 8. Click on 'Finish' to see 4 projects getting created from archetype
  Maven main/parent project that has web project (jaxwsSample1WS), ear project (jaxwsSample1WSEAR) and Webservice client jar(jaxwsSample1Client)

9. Right Click on jaxwsSample1 project and select 'Set as Main Project'. This is only for NetBeans. As pom.xml of jaxwsSample1 has the information of other 3 projects as modules, a clean,build and install goals on this project builds the other 3 projects too.

IRAD7.5 has some difficulties in identifying maven enabled parent-child projects.

10. Right click on jaxwsSample1 and select Clean and Build menu item  
 

11. Observe the output on console. The jaxwsSample1WS and jaxwsSample1WSEAR are successful and jaxwsSample1Client is failed.
It is because client needs .wsdl file of WS to build successfully.
12. Deploy jaxwsSample1WSEAR-1.0-SNAPSHOT.ear into JEE5 Server (ex. Glassfish v3) and then run maven for client with some changes in pom.xml of client.

13. Run AdminConsole of server (Glassfish) to deploy the application. Any JEE5.0 Server that has JAXWS enabled can be used. Deploy jaxwsSample1\jaxwsSample1WSEAR\target\jaxwsSample1WSEAR-1.0-SNAPSHOT.ear file.




14. Click on 'OK" button deploy




15. Verify to access the deployed application at http://localhost:8080/jaxwsSample1/AppWSService?wsdl . The server and port can be different in your scenario. If there is no error (404, 500 or 403) then see view source of page using context-menu on page.










16. Open pom.xml for client and refer to use wsdl provided by WebService running in server.














The client can use .wsdl file available with source of service or obtain while service is running. 
In production (not demo) version it is recommended to copy .wsdl file into client source instead of obtaining from server.

17a.  Now rebuild all the projects  or just client.  Please move to Netbeans to select jaxwsSample1Client as Main Project to build only client















17b. Select 'Clean and Build' from context-menu to just build client.







All above steps instructed you to create a webservice (war and ear) and a client (jar) to use the webservice.

Please notice all the output files (.war, .ear and .jar) files are created at maven local repository (USERLOCAL/.m2\repository\org\mycompany).


Have fun.

Tuesday, March 9, 2010

Unable to find javac compiler while running Ant from Maven2.

If your maven2 pom.xml is using a plugin (maven-antrun-plugin) to run ANT build.xml and a javac task is used in it to compile source then it is very usual to get the following error.

Reason: An Ant BuildException has occured: The following error occurred while executing this line:
C:\maventest\build.xml:79: Unable to find a javac compiler;
com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK.
It is currently set to ..***\***\jre.

Cause: When Maven2 runs pom.xml it uses the jre (%JAVA_HOME%\jre) instead of %JAVA_HOME% and when ant build is using 'javac' task then maven2 tries to find javac in %JAVA_HOME%\jre.

Solution: Any of the following three can be used. Solution 1 is prefered.

1. Provide a property in pom.xml for maven-antrun-plugin to fork/use javac as an external process. Please see image for reference
2. In pom.xml for maven-compiler-plugin add a property to fork out the javac process.
Read more about the properties of this plugin at http://maven.apache.org/maven-1.x/plugins/java/properties.html

<properties>
<maven.compile.fork>true</maven.compile.fork>
<properties>
 
either under  element or under of  maven-compiler-plugin.
 
3. In ant build.xml at javac task use an attribue fork='true'