Saturday, May 29, 2010

JAX WS Web Services

If you cannot read this post properly, please go to the source at <a href="http://kolawarsunil.blogspot.com">http://kolawarsunil.blogspot.com</a>.

In this blog, we will see how easy it is to write a simple WebService and then add security to it.

First, write the Java Class with the methods that we are going to expose as a Web Service.

Example:


 

public class UserService{

public String getFullName(Long userId){

return "FULL NAME";

}

public String getSecretName(Long userId){

return "SECRET NAME";

}

}


 

Now, This simple java class methods can be exposed as a WebService, by adding few annotations(Java 6). After adding few annotations, the same class will look something like this.


 

@WebService(serviceName="UserWebService",name="UserServiceOperations",targetNamespace="http://ws.user.services.com/xsd/userservice")

public class UserService{

@WebMethod

public String getFullName((@WebParam(name = "userId") Long userId){

return "FULL NAME";

}


 

public String getSecretName(Long userId){

return "SECRET NAME";

}

}


 

As you can see in the above code, we add the @WebService annotation to expose this class as a web service, the attributes like serviceName, name, targetNamespace etc are optional. The serviceName need NOT be same as the Java Class name.

The @WebMehthod annotation exposes the method in the WebService. As one can see that 'getSecretName' method does not have the annotation, so it is not exposed as a WebService method.


 

The @WebParam is also not mandatory, but will be useful when the WSDL is generated from this class (we will look into generating WSDL in a moment) and the arguments the method takes are named as the value given in the @WebParam(name="something"). It would help the end user understand what that argument really is, instead of him knowing that it's a Long.


 

Once you write all the necessary annotations, we can go ahead and generate the WSDL from the Java Class (bottom up approach).

In maven, your pom.xml would look something like this (after adding the necessary dependencies and plug-ins to generate the WSDLs)


 


 

<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">


 

<parent>

<artifactId>parent_artifact</artifactId>

<groupId>parent_group</groupId>

<version>0.1</version>

</parent>


 

<modelVersion>4.0.0</modelVersion>

<groupId>group</groupId>

<artifactId>artifact</artifactId>

<version>0.2</version>

<packaging>war</packaging>

<name>User Service (WEB)</name>


 


 

<dependencies>

<dependency>

<groupId>org.jvnet.jax-ws-commons.spring</groupId>

<artifactId>jaxws-spring</artifactId>

<version>1.8</version>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>servlet-api</artifactId>

<version>2.5</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-test</artifactId>

<version>2.5.6.SEC01</version>

<scope>test</scope>

<exclusions>

<exclusion>

<artifactId>junit</artifactId>

<groupId>junit</groupId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.4</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-web</artifactId>

<version>2.5.6.SEC01</version>

</dependency>

<dependency>

<groupId>com.sun.xml.ws</groupId>

<artifactId>jaxws-rt</artifactId>

<version>2.1.3</version>

<exclusions>

<exclusion>

<artifactId>junit</artifactId>

<groupId>junit</groupId>

</exclusion>

</exclusions>

</dependency>

</dependencies>


 


 

<build>

<finalName>user_services_web</finalName>


 

<resources>

<resource>

<directory>src/main/resources</directory>

</resource>

</resources>

<testResources>

<testResource>

<directory>src/test/resources</directory>

</testResource>

</testResources>


 

<plugins>

<plugin>

<groupId>org.codehaus.mojo</groupId>

<artifactId>jaxws-maven-plugin</artifactId>

<version>1.10</version>

<executions>


 

<execution>

<id>Generating User artifacts</id>

<goals>

<goal>wsgen</goal>

</goals>

<configuration>

<sei>com.services.ws.UserService</sei>

<genWsdl>true</genWsdl>

<keep>true</keep>

<resourceDestDir>src/main/webapp/WEB-INF/wsdl</resourceDestDir>

</configuration>

</execution>


 

<execution>

<id>Generating Consumer artifacts</id>

<goals>

<goal>wsgen</goal>

</goals>

<configuration>

<sei>com.services.ws.ConsumerWS</sei>

<genWsdl>true</genWsdl>

<keep>true</keep>

<resourceDestDir>src/main/webapp/WEB-INF/wsdl</resourceDestDir>

</configuration>

</execution>

</executions>


 

</plugin>


 

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-plugin</artifactId>

<configuration>

<skipTests>true</skipTests>

</configuration>

</plugin>


 

</plugins>

</build>


 

<repositories>

<repository>

<id>maven-repository.dev.java.net</id>

<name>Java.net Repository for Maven 1</name>

<url>http://download.java.net/maven/1/</url>

</repository>

<repository>

<id>maven2-repository.dev.java.net</id>

<name>Java.net Repository for Maven 2</name>

<url>http://download.java.net/maven/2/</url>

</repository>

</repositories>


 

<pluginRepositories>

<pluginRepository>

<id>maven2-repository.dev.java.net</id>

<url>http://download.java.net/maven/2/</url>

</pluginRepository>

</pluginRepositories>


 

</project>


 

As you can see in the above file, wsgen is used to generate the WSDL and XSD's. We need to specify the Service Endpoint Interface (SEI), in the tags <sei></sei>, where we specified the UserService class, with its fully qualified name (i.e along with the package etc)


 

You can right click on you pom.xml and select run as 'maven package', this will generate the WSDL's and keep them in the Directory location specified in the POM, in our case, we specified, <resourceDestDir>src/main/webapp/WEB-INF/wsdl</resourceDestDir>.


 

In case of any errors, open command prompt, go to the directory that contains the pom.xml and run the following command "mnv -X package". This will show the errors in detail (i assume you have mvn in your PATH, so that 'mvn' command can run from anywhere).


 

If you are using WebLogic 10.3, then @AutoWired (auto wiring in spring) does not work and we need to either inject the required bean in the context file or do the following


 

public class UserService{

@Resource

private WebServiceContext wsContext;


 

@Autowired

UserDAO userDao;


 

public UserDAO getUserDao() {


 

if (userDao== null) {

ServletContext servletContext = (ServletContext) wsContext.getMessageContext().get( MessageContext.SERVLET_CONTEXT);


 

WebApplicationContext webContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);

userDao= (UserDAO ) webContext.getBean("userDao");

}

return userDao;

}


 

}