Archive

Posts Tagged ‘java’

SOAP orchestration with java:axis2

August 29th, 2008 Andrew Zuercher No comments

Problem Definition

Are you considering integrating a bunch of web services together but may not feel too comfortable with the vulnerabilities of a mash-up approach, the overhead of setting up and using an ESB, or writing a bunch of mind numbing spilling crushing service transformation code? If thats what you want then, yeah sure that would work for a problem definition.

How does it do it?

The java:axis2 plugin (an appcelerator plugin) installs an appcelerator command that can be run either silently or prompt for input to generate and build axis2 stubs from your WSDL url. Once the stubs have been built, the command then creates a java appceleator-based class with services for each corresponding soap endpoint. The solution makes use of code generation so that you may enhace the services should you so desire. Serialization is also taken care of by transforming to/from the JSON model to the Axis2 model so that making the changes to the service mapping is clean and simple.

How would 1 set it up?

Before you can use the plugin, you need to download axis2 and setup your path appropriately. Its pretty easy, just extract axis2 and set your AXIS2_HOME environment variable. Now you can add the plugin to your java project (named $PROJECT):

app install:plugin java:axis2
cd $PROJECT
app add:plugin java:axis2

How do I use it?

Now that you’ve added the plugin, you can now implement the service orchestration for invoking a SOAP endpoint. Lets assume that your wsdl is at http://localhost:8080/axis/services/QueryPort?wsdl. This is how it would flow for you in prompted mode

app gen:axis2
Whats the url for your wsdl?
http://LODVM1044:8080/axis/services/QueryPort?wsdl
What directory do you want to use for storing the axis stubs? [src/axissource]
src/axissource/queryport
What package name do you want to use for your axis stubs? [my.axis]
queryport.axis
What directory do you want to generate the services to? [app/services]
app/services
What package name do you want to use for your appcelerator services? [my.service]
queryport

Alternatively you could run this silently:

app gen:axis2 --axisdir=src/axissource/queryport --axispackage=queryport.axis \
--wsdl=http://localhost:8080/axis/services/QueryPort?wsdl --silent=true --appcpackage=queryport

Here is a sample snippet of the code that will be generated to map your appcelerator services to a web service call:

package cmdb.service;
 
import org.appcelerator.annotation.Service;
import org.appcelerator.messaging.Message;
 
public class QueryService {
 
	@Service(request = "graphQuery.request", response = "graphQuery.response")
	public void graphQuery(Message request, Message response) throws Exception {
		uery param = (axis.query.QueryServiceStub$Query) AxisUtil.toAxisObject(request, axis.query.QueryServiceStub$Query.class, "param");
		axis.query.QueryServiceStub$QueryResult result = new axis.query.QueryServiceStub().graphQuery(param);
		response.getData().put("result",AxisUtil.toMessageDataObject(result));
	}
}

Note that for this to work you will have to upgrade your Appcelerator installer to 1.1.20+ (next release to be out shortly), I’ve updated mine off of the svn trunk. To check your installer:

app --version

Some more details on how to test

Now the question is, how do i know how to construct my request parameters? You can use the AxisUtil class to help you out, here is a sample snippet for my parameter into the web service, the model class Query:

Query param = createQuery(); //however you want to create your model object
System.out.println(AxisUtil.toJSONObject(param).toString());

the request body will directly reflect that ex:

{"query":{"itemTemplate":[{"contentSelector":null,"id":{"value":"ALL_CI1s"},
 
 
 
 
"instanceIdConstraint":null,"recordConstraint":[],"suppressFromResult":false,
"xpathExpression":[]},{"contentSelector":null,"id":{"value":"ALL_CI2s"},"instanceIdConstraint":null,
"recordConstraint":[],"suppressFromResult":false,"xpathExpression":[]}],
"relationshipTemplate":[{"contentSelector":null,"depthLimit":null,
"id":{"value":"ALL_Relations"},"instanceIdConstraint":null,"recordConstraint":[],
"sourceTemplate":{"maximum":22,"minimum":0,"ref":{"value":"ALL_CI1s"}},
"suppressFromResult":false,"targetTemplate":{"maximum":0,"minimum":0,"ref":{"value":"ALL_CI2s"}},
"xpathExpression":[]}]}}

This utility will help you to see how the data is structured. For a more detailed example unit test check out SerializationTest.java

Wrap Up
In this post we demonstrated:

  • what the plugin does and the problems it solves
  • how to set it up and use it, as well as how to test

this blog cross-posted at http://www.appcelerant.com/java_axis2.html

Technorati Tags: , , , ,

Categories: announcements Tags: , , , ,

JSON serialization with appcelerator java services

February 8th, 2008 Andrew Zuercher No comments

Using Model Objects

The issue of serializing/transforming model objects is not new, heck I’ve been doing this for quite some time:

  • rmi (ejb/corba)
  • xml (jms, soap, etc..)
  • json

JSON is not the only way to serialize objects for web2.0 applications, but its the most abundant and heavily used throughout our framework. Doing this is actually really easy to do with appcelerator IModelObejects. Our IModelObjects can easily be used along with hibernate for persistance, but lets leave that for later for now. When you define your Model classes, there are some very simple things to keep in mind:

  • annotate your attributes with @MessageAttr
  • have your class implement IModelObject

Here is a simple example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class User implements IModelObject, Serializable {
  private static final long serialVersionUID = 1L;
 
  @MessageAttr
  public String name;
 
  public void setUsername(String username) {
    this.username = username;
  }
 
 public void setPassword(String password) {
   this.password = password;
  }
 
  ...
}

Unit test it

Now to test the rendering of our object to JSON with a simple junit test…. As you can see, we leverage the Appcelerator framework to serialize our objects to JSON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class ForumTest extends TestCase { 
 
public void testSimple() {
  User user = createUser();
  Message message = new Message();
  JSONMessageDataObject data = new JSONMessageDataObject();
  message.setData(data);
  message.getData().put("user", user);
  message.getData().put("count", 1);
  String messagestr = data.toDataString();
  assertEquals(messagestr,"\"user\":{\"password\":\"pwd\",\"threads\":0,\"fullName\"
  :\"antewew\",\"username\":\"azuercher\",\"state\":\"mystate\",\"email\":\"email\",
  \"posts\":0,\"id\":0},\"count\":1}");
}
 
private User createUser() {
  User user = new User();
  user.setEmail("email");
  user.setFullName("ante wew");
  user.setId(new Long(0));
  user.setPassword("pwd");
  user.setPosts(new Long(0));
  user.setState("mystate");
  user.setThreads(new Long(0));
  user.setUsername("azuercher");
  return user;
}
 
}

Dealing with recursion

Whats always a bit of a tangle is understanding how to deal with the recursive/circular relationship.
If you take a look at JSONObject you will see 2 overridden methods for createBean

1
2
public static JSONObject createBean(IModelObject object,MessageAttr parentAtt, String context,String[] parentSuppres,int level, int maxlevels)
public static JSONObject createBean(IModelObject object)

The latter is obviously a bit more simple, but the former is where the power is. In the MessageAttr annotation, you can provide the suppress attribute which is a comma separated list of aggregates (using bean.name notation to not serialize). This is used for attributes in your IModelObject implementation where the association is with another IModelObject. The following model is for a forum object model where the following aggregate hierarchy exists:

1
2
3
* Forum
** ForumThread
*** Post

In the snippet below, I’ve omitted the getter/setter methods for the aggregates for simplicity.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class User implements IModelObject, Serializable {
  @MessageAttr (suppress="user,thread.lastPost")
  public Post lastPost;
}
 
public class Post implements IModelObject, Serializable {
  @MessageAttr(suppress="lastPost,forum.lastPost")
  public Forumthread thread;
 
  @MessageAttr (suppress="lastPost")
  public User user;
}
 
public class Forumthread implements IModelObject, Serializable {
  @MessageAttr (suppress="lastPost")
  public Forum forum;
 
  @MessageAttr (suppress="thread,user.lastPost")
  public Post lastPost;
}
 
public class Forum implements IModelObject, Serializable {
  @MessageAttr (suppress="thread.forum,thread.lastPost,user.lastPost")
  public Post lastPost;
 
}

Rolling your own serialization

Assuming you know what your JSON string is going to look like, you can use our RawMessageDataList and RawMessageDataObject to serialze your objects. This is pretty useful if you already are rendering JSON in an existing framework and don’t want to have to transform to and back again. The snippet below shows with static strings just so that you get the idea:

1
2
3
4
5
6
7
8
9
IMessageDataList people = new RawMessageDataList(
"[{'name':'joe','age':22},{'name':'jane','age':33}]");
 
IMessageDataList dog = new RawMessageDataObject("{'breed':'doberman','weight':78}");
 
Message message = new Message();
message.setData(new JSONMessageDataObject());
message.getData().put("people", people);
message.getData().put("dog", dog);

Using Coarse Grained objects

This is probably the simplest/prettiest way to implement your services assuming that you aren’t interested in using fine grained classes that are associated with most of today’s persistence frameworks. Here is how you would create a single compound JSON object:

1
2
3
4
5
IMessageDataObject dog = MessageUtils.createMessageDataObject();
obj.put("breed","doberman");
obj.put("wieght",78);Message message = new Message();
message.setData(new JSONMessageDataObject());
message.getData().put("dog", dog);

and now with a collection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
IMessageDataList<IMessageDataObject> people =
MessageUtils.createMessageDataObjectList();
 
IMessageDataObject joe = MessageUtils.createMessageDataObject();
joe.put("name","joe");
joe.put("age",22);
 
IMessageDataObject jane = MessageUtils.createMessageDataObject();
joe.put("name","jane");
joe.put("age",33);
 
people.put(joe);
people.put(jane);
 
Message message = new Message();
message.setData(new JSONMessageDataObject());
message.getData().put("people", people);

Summary

As you can see there are quite a bit of alternatives for you based on what your needs are to accommodate your service implementations. I’ve personally used all of the above as I’ve implemented:

  • Model Objects: using hibernate for persistence
  • Custom Serialization: for integrating with pre-rendered objects (commons-monitoring)
  • Coarse Grained: in implementing a dashboard/event driven solution

cheers and enjoy,

-andrew

cross-posted @ http://zuerchtech.com/2008/2/8/json-serialization-with-appcelerator-java-services

Technorati Tags: , , ,

Categories: announcements Tags: , , ,