This blog is mainly about Java...

Showing posts with label axis2. Show all posts
Showing posts with label axis2. Show all posts

Monday, November 23, 2009

Axis 2 gotcha

Just wanted to give a quick GOTCHA I discovered with Axis 2. The other day I wanted to install and use lombok (which is AWESOME by the way).

However lombok needs Java 6 to run, and my WebService was compiled with Java 5, so I changed to Java 6, recompiled, but obviously forgot to recompile the WebService client stubs.
 I didn't get any exception that remotely told me that I had a class version issue. However, I got this exception:
com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
After reverting back to Java 5, everything worked just fine. So just a heads up.

Wednesday, February 4, 2009

How to create and use a WebService with Axis 2 and Seam 2.x in JBoss 4.x

In this example, I will show how you can create a Webservice using Axis 2.
First of all, download the latest version of Axix 2 from http://ws.apache.org/axis2/

To create a WebService in Java EE 5 you can use the annotation @WebService.
We also annotate this class as a seam component so that we can incorporate it in our existing business logic.

This is our WebService:

package somepackage.webservice;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.persistence.EntityManager;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;

@Name("fooService")
@Stateless
@WebService(name = "FooService", serviceName = "FooService")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class FooService implements FooServiceLocal {

@In EntityManager entityManager;

@In Credentials credentials;

private boolean login(String username, String password) {
credentials.setUsername(username);
credentials.setPassword(password);
Identity.instance().login();
return Identity.instance().isLoggedIn();
}

private boolean logout() {
Identity.instance().logout();
return !Identity.instance().isLoggedIn();
}

@WebMethod
public List<FooCanonical> getFoo(@WebParam(name = "username")
String username, @WebParam(name = "password")
String password, @WebParam(name = "orgnumber")
String orgnumber) {
// orgnumber can be null!
if (username == null || password == null) {
return null;
}
//First thing we do is to login to ensure that the user has the correct username/password
//We are using basic seam login method
boolean isLoggedIn = login(username, password);

if (isLoggedIn) {

List<FooCanonical> returnList = new ArrayList<FooCanonical>();
//Do some stuff with the list
//Remember to log out
logout();
return returnList;
} else {
// Probably wrong username password
return null;
}
}

}


Next what we need to do, is create a way for this webservice to interact with JBoss through our SOAP definition. We do that by creating a xml file called
standard-jaxws-endpoint-config.xml

<jaxws-config xmlns="urn:jboss:jaxws-config:2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="urn:jboss:jaxws-config:2.0 jaxws-config_2.1.xsd">
<endpoint-config>
<config-name>Seam WebService Endpoint</config-name>
<pre-handler-chains>
<javaee:handler-chain>
<javaee:protocol-bindings>##SOAP11_HTTP</javaee:protocol-bindings>
<javaee:handler>
<javaee:handler-name>SOAP Request Handler</javaee:handler-name>
<javaee:handler-class>org.jboss.seam.webservice.SOAPRequestHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</pre-handler-chains>
</endpoint-config>
</jaxws-config>

And place this file in the $JBOSS_HOME/resources/META-INF directory.
Now you are done! Deploy your application and look in
http://localhost:8080/jbossws/services 
and see if your WebService is correctly deployed and the wsdl available.
This should look something like this:

Endpoint Namejboss.ws:context=foo-foo,endpoint=FooService
Endpoint Addresshttp://localhost:8080/foo-foo/FooService?wsdl

Next, we will use the Axis2 framework to create client stubs by using axis2-1.4.1 and the script wsdl2java. Navigate to $AXIS_HOME/bin and type in the following command:
./wsdl2java.sh -uri http://127.0.0.1:8080/foo_foo/FooService?wsdl -o build/client

This command will create an ant script under the directly build/client.
Now go to build/client and type ant after setting $AXIS_HOME. This will generate FooService-test-client.jar which we now can use to retrieve data from the WebService in the client. I recommend changing the name to something more appropriate.

In your client, you can call the getFoo WebMethod like this:

FooServiceStub stub;
GetFoo getFoo;

stub = new FooServiceStub();
getFoo = new FooServiceStub.GetFoo();
getFoo.setUsername("username");
getFoo.setPassword("password");
getFoo.setOrgnumber("1234");

FooServiceStub.GetFooE fooImpl = new FooServiceStub.GetFooE();
fooImpl.setGetFoo(getFoo);

//Retrieve the List as an array
FooCanonical[] get_return = stub.getFoo(fooImpl).getGetFooResponse().get_return();
//Do what you want with the array

Note that even if you return a List from the WebService, you will get it as an array. But it is quite easy to put it in a List in the client afterwards. Also remember that the username and password is sendt in clear text, so you might want to send it through https, so it is encrypted.

Labels