Dec/090
Java Builds Using ANT and Enunciate
In a previous entry I gushed over the features that Enunciate provided. Today, I’m going to walk through how to integrate Enunciate with your ANT script and provide a true Service Oriented Architecture which makes your web services universally accessible. I’ve chosen to write on the integration of Enunciate with ANT as opposed to Maven, because I generally use ANT to create my build scripts.
For the purposes of this example I want to create a simple SOAP service and allow the service to be utilized via AMF so that it is optimized for Flash integration. Let’s see how easy it is to do this.
The first task for using Enunciate to generate your web services, is to make sure that all of your service interfaces and implementations have been given the correct Annotations. For the purposes of this example I’ve created a simple interface, which I’ve included below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package com.softwarejesus.enunciate.service; import java.util.List; import javax.jws.WebService; import com.softwarejesus.enunciate.vo.SampleVO; @WebService ( targetNamespace = "http://softwarejesus.com/EnunciateSample", serviceName = "sampleService" ) public interface ISampleService { List<SampleVO> getSamples(); SampleVO updateSample(SampleVO sample); } |
The only annotation I had to include was the @WebService annotation. You can read up on the WebService Annotation here. By using the WebService Annotation you have now indicated to Enunciate that this will be a SOAP endpoint.
Here is my service implementation, notice that it too has the WebService Annotation:
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 | package com.softwarejesus.enunciate.service; import java.util.List; import javax.jws.WebService; import com.softwarejesus.enunciate.vo.SampleVO; @WebService( endpointInterface="com.softwarejesus.enunciate.service.ISampleService" )public class SampleService implements ISampleService { @Override public List<SampleVO> getSamples() { // TODO Auto-generated method stub return null; } @Override public SampleVO updateSample(SampleVO sample) { // TODO Auto-generated method stub return null; } } |
Once we’ve written our web services, and provided the correct annotations, we’re ready to create our ANT build script. For the purposes of this example, I’m going to add all of the jar files in the {ENUNCIATE_HOME}/lib directory as well as all the jar files in the spring and amf module directories to the ANT build path. Next, we’re going to create the ‘enunciate’ task, which is located in {ENUNCIATE_HOME}/lib/enunciate-core-1.xx.jar.
Now that we’ve configured ANT a bit, let’s write our ANT script.
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 | <?xml version="1.0" encoding="UTF-8"?> <!--Ant build file for building the sample API.--> <project default="war"> <!-- - - - - - - - - - - - - - - - - - target: enunciate - - - - - - - - - - - - - - - - - --> <target name="enunciate"> <!--define the task...--> <mkdir dir="${basedir}/target/EnunciateSample/"/> <enunciate dir="${basedir}/../src" configFile="${basedir}/enunciate.xml" > <export artifactId="app.dir" destination="target/EnunciateSample/"/> </enunciate> </target> <target name="war" depends="enunciate"> <copy todir="target/EnunciateSample/WEB-INF/lib/"> <fileset dir="../buildLibs/" /> </copy> <war destfile="target/EnunciateSample.war" webxml="target/EnunciateSample/WEB-INF/web.xml"> <fileset dir="target/EnunciateSample" /> </war> </target> </project> |
Let’s look at the ‘enunciate’ task. First, need to point enunciate in the direction of our source code, which is done via the “dir” attribute. Second, you have to create a configuration xml that enunciate will use to determine what will be built.
The export node is important, because it tells enunciate what artifacts we want it to produce. Here’s a full list of the artifacts that you can specify. For this example, I wanted enunciate to give me the “exploded” war file. I don’t want enunciate to generate my war file, because I’ve found that enunciate does not include some jars that are necessary for the deployment to Tomcat 6.
Now let’s look at the configuration file that enunciate uses:
1 2 3 4 5 6 | <enunciate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.16.xsd"> <modules> <amf disabled="false" swcDownloadable="false" asSourcesDownloadable="true"/> </modules> </enunciate> |
Enunciate has a whole slew of modules that you can incorporate into your build, but for this sample I wanted to keep it as simple as possible. I need to indicate that I want to include AMF for my services, so I add the ‘amf’ node and set the disabled attribute to false. Now, as I mentioned in my earlier post, I haven’t been able to get the swc that enunciate produces to work exactly as I want it to, so I’m going to tell it not to forget the swc, but generate the Action Script source.
I really have enjoyed working with Enunciate thus far, I think it’s a wonderful tool for those who truly believe in a Service Oriented Architecture, because it allows you to provide numerous gateways to the exact same web services. Along with generating all of the endpoints for you, it will, with some work on the developer’s part, generate all of the documentation that any client would need to connect to and utilize the resulting services.
Sample project here.
Nov/090
Quick-Hit: Enunciate
In my most recent work project I was asked to develop a set of middle tier services to allow users to connect to commonly used pieces of data in the organization. As I gathered requirements from different developers that were hoping to utilize these services I found that my standard technology stack would not suffice for a number of reasons. First, the organization I was working with had very strict regulations on technologies which could be used. But most importantly, the vast majority of middle-tier web services I’ve done recently have provided data solely to Flex applications, but in this new project I had a number of different clients wanting to pull data.
I knew immediately that I wanted to write one set of web services but allow access to it via a couple of different gateways: AMF and SOAP. I started by asking around to numerous guys I know to see if they recommended anything that would make the SOAP gateway as easy as possible to write. One article that my coworker Andrew sent me pointed me in the direction of Enunciate.
As I sifted through all of the information in the site, I thought, there’s no way they can provide this much functionality for free, but I have to say, it’s pretty awesome. So what does enunciate do? Well enunciate allows you the ability to write the interfaces and implementations of your web services, add a few choice annotations, and Encunciate will configure all of your SOAP, REST, as well as AMF endpoints. Enunciate does all this via an xml based build script which fits in nicely with both ANT and Maven.
Along with all of the service configurations, Enunciate will also export libraries that different client apps can use to connect to your middle tiers. Enunciate will export a Flash library, Objective C (for you iPhone developers), as well as numerous others. I have not been able to use the swc in my eclipse workspace, but I’ve started exporting the source and modifying it as needed.
Another feature that’s really nice about it enunciate, is that it automatically generates all of the documentation for your web services. It gives detailed information about what is available via REST and SOAP. The AMF documentation is not as detailed as SOAP or REST, which is a little disappointing.
All-in-all this tool has blown my expectations away. My proof of concept was completed in no time at all. I plan to do a full how-to blog entry on Enunciate before the end of the year.
Aug/091
Java Middle-Tier Using Ibatis
This is going to be my first entry in a series on how to quickly and efficiently develop the middle-tier portion of an enterprise level flex application that will allow you to communicate with your application via the most efficient and simple means available, that being Remote Procedure Calls. By the time I finish the series, my hope is that you will be able to knock out the middle-tier portion of your application in no time at all, giving you a maximum amount of time to develop your front end Flex app.
The focus of this particular entry is ibatis, which is a framework which allows you to configure the population of java objects from the database using xml files. Ibatis has a ton of features which you can use, and detailing the full litany of them is a more laborious task than I’m up for. For the purposes of this entry, I’m going to show you how to map database fields to java fields, select, update, and insert data.
For the sake of these examples, I will have an embarassingly simple object model, reflected by the following VO:
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 | package com.softwarejesus.ibatis.domain; public class FirstObject { private String fieldOne; private String fieldTwo; private int fieldThree; public String getFieldOne() { return fieldOne; } public void setFieldOne(String fieldOne) { this.fieldOne = fieldOne; } public String getFieldTwo() { return fieldTwo; } public void setFieldTwo(String fieldTwo) { this.fieldTwo = fieldTwo; } public int getFieldThree() { return fieldThree; } public void setFieldThree(int fieldThree) { this.fieldThree = fieldThree; } } |
The first step in using ibatis, is to add the necessary jar files to your application’s buildpath. The jar files are available at the ibatis site here
Step two, is to determine what type of interactions you’ll need with your database. Here’s my Data Access Object
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | package com.softwarejesus.ibatis.dao; import java.io.IOException; import java.io.Reader; import java.sql.SQLException; import java.util.List; import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; import com.softwarejesus.ibatis.domain.FirstObject; public class FirstDao { private static SqlMapClient client; public FirstDao() { try { Reader reader = Resources.getResourceAsReader("sql-map-config.xml"); client = SqlMapClientBuilder.buildSqlMapClient(reader); reader.close(); } catch (IOException e) { System.out.println("There are better ways to do this, and I'll show you in a later post"); } } public List<FirstObject> getAllFirstObjects() { List<FirstObject> returnList = null; try { returnList = client.queryForList("getAllFirstObjects"); } catch (SQLException sqlE) { sqlE.printStackTrace(); } return returnList; } public List<FirstObject> getFirstObjects(String param) { List<FirstObject> returnList = null; try { returnList = client.queryForList("getFirstObjects"); } catch (SQLException sqlE) { sqlE.printStackTrace(); } return returnList; } public void updateFirstObject(FirstObject object) { try { client.update("updateFirstObject", object); } catch (SQLException sqlE) { sqlE.printStackTrace(); } } public void insertFirstObject(FirstObject newObject) { try { client.insert("insertFirstObject", newObject); } catch (SQLException sqlE) { sqlE.printStackTrace(); } } } |
As you can see, I have two ways I can retrieve data, one will return all the data, the other will select based on some input criteria. I also have an update and insert method. The constructor creates a SqlMapClient object, the SqlMapClient object is basically where all the magic happens with ibatis. I won’t focus on the constructor, because my next entry will show you how to use Spring to populate this, and many other necessary objects.
Now that we know what interactions we want to have with the database, we need to set up our SQL-Map XML. My SQL Map includes only 6 different node types: typeAlias, resultMap, result, select, update, and insert.
The typeAlias node creates a shorthand Alias for a specific java class.
The resultMap node create another Alias, indicating how a specific set of fields will populate a java object.
The result node matches a specific result set field to a java field.
The select, update, and insert nodes should all be relatively self-explanatory.
Here’s my SQL-Map
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 30 31 32 33 34 35 36 | <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlMap namespace="Model"> <typeAlias alias="myFirstObject" type="com.softwarejesus.ibatis.domain.FirstObject" /> <resultMap id="firstObjectResult" class="myFirstObject"> <result property="fieldOne" column="oneField"/> <result property="fieldTwo" column="twoField"/> <result property="fieldThree" column="threeField"/> <resultMap> <select id="getAllFirstObjects" resultMap="firstObjectResult"> Select * from firstTable </select> <select id="getFirstObjects" resultMap="firstObjectResult" parameterClass="java.lang.String"> Select * from firstTable where oneField = #value# </select> <update id="updateFirstObject" parameterClass="myFirstObject"> UPDATE firstTable SET oneField = #fieldOne# ,twoField = #fieldTwo# ,threeField = #fieldThree# WHERE oneField = #fieldOne# </update> <insert id="insertFirstObject" parameterClass="myFirstObject"> INSERT INTO firstTable VALUES (#fieldOne#, #fieldTwo#, #fieldThree#) </insert> </sqlMap> |
Obviously this was a very simple example of what can be done using ibatis. I like how flexible ibatis is though, notice how the database calls (select, update, and insert nodes) have an attribute called parameterClass. What’s nice is that you can set the parameter class to either a typeAlias or the fully qualified Java class name. I almost always use the typeAlias, for the sake of readability, but, it’s not necessary to do so. The same goes for the result type, you can either use a resultMap defined in your SQL Map or set the resultClass attribute to a fully qualified Java class.
You may have noticed that sometimes in the select/insert/update portions of my SQLMap I use #value# to inject values into the SQL and sometime I use $value$ to inject values. The difference between the two is that using the #value# formats the value to ensure that it is SQL, for example handling apostrophes in Strings. Whereas, $value$ indicates that the value is already SQL formatted.
In the DAO all I had to provide ibatis with was the ID of the SQL statement I wanted to run, and any parameters necessary for the statement, that’s it! I love using ibatis because it makes my java piece so tiny and essentially maintenance free.
One thing to be careful of when using ibatis, is that it struggles with null values returned from the database, usually you’ll have to indicate in the resultMap what the java type is if there’s a null value returned.
Ibatis has tons of really great features, and I’ve only scratched the surface on them here. But one of the things I like the most is if the result set fields match the java fields, you don’t have to define a resultMap, because ibatis will handle it for you.
Aug/090
Quick-Hit: JOTM on Tomcat for LiveCycle
If you’ve tried to set up a Tomcat Server to run LiveCycle Data Services you may know that it can be quite a bit more difficult than you anticipated, especially if you’re familiar with BlazeDS.
I thought things were going well until I tried to update the data that I had received from LiveCycle. At that point I received the infamous “Unable to access UserTransaction in DataService” error.
Adobe has some great information on fixing it, available here.
I followed their advice, but it still wasn’t working. Finally, one of my friends suggested that instead of putting the jar files in the {CATALINA_HOME}/common/lib folder that we put them in our WEB-INF/lib folder. We restarted our Tomcat Server, and thankfully it worked like a charm.