Sunday, February 16, 2014

Separate Properties from WAR

Separating properties from wars, there are many reasons and there are many ways. If you are still generating multiple wars, each for each level, you are out. Catch up, my friends, it is already the year of 2014.

Among all these almighty solutions, there is this simple and easy one, with JBoss 5.1.

First create a myapp-service.xml like this,



This myapp-server.xml will be deployed to JBoss deploy folder same as the war file.

Then in the appContext.xml, add a PropertyPlaceholderConfigurer.



Now you can use these properties in the appContext.xml like that,



To use the properties like myapp.props1, you need to define the field in the bean class like "private String[] props1;" then your props1 will be an array of aaa and bbb.

Now let's see that aaa and bbb need to be populated into a drop down list in HTML page.

First, create a JSON web service to serve the AJAX request. Remember, aaa and bbb will be sent down as {"aaa", "bbb"}.

In the HTML page, it will look like,



After selection, use $("#mydropdownid").val() to obtain the selected value. Remember it will be "aaa" or "bbb", not aaa or bbb. So when post it back to web service, use it straight forward, don't JSON stringfy it.

Wednesday, February 12, 2014

Use Maven to Manage Javascript Libraries

Usually we download javascript libraries and add them to web applications. It is simple and easy. However, it becomes headache when we need more and more libraries and the application grows big.

The problem is that some libraries are only compatible with others at certain versions. Also during the lifetime of the application, we need to add new features which will only be achievable with a newer version of some libraries. Now, are they still compatible? Or are they not anymore?

We will inevitably need to run testings back and forth to find the right mix. So what shall we do to minimize the hustle and headache?

Here is how I do it.

I download javascript libraries and install them into MyEclipse local maven repository. This is not ideal, because my teammates will need to repeat the installation. Ideally, we should be able to download it from central maven repository just like spring-core and spring-ws.

Webjars.org gives it a nice try to centralize popular javascript libraries and provide them as jar files. But I don't like its concept to use them as resources via classpath.

So I use maven overlays.

Here is how I define them in pom.xml.



It's not over yet. The Maven install process will create a myApp.war file, but MyEclipse doesn't deploy it to my JBoss server. So again I turn to Maven to solve this problem.

Here is how I deploy myApp.war to my JBoss server.



I use cargo-maven2-plugin which is not ideal either. Simply because some guys keep on thinking older is better, instead of upgrading to JBoss 7, we stuck with JBoss 5.1. Otherwise, jboss-as-maven-plugin would be beautiful.

Besides I use ${jboss.home} to point to my JBoss installation which is very necessary. Because I will check in the pom.xml to Subversion and my teammates will get the same pom.xml. If I hard code my JBoss home directory here, they will need to change it for their environment. So the solution is to introduce the settings.xml.



This settings.xml needs to put under C:\Users\[userid]\.m2 directory.

Now everything should be good.

MyEclipse Install/Uninstall Zip File to Maven Local Repository

MyEcliplse Blue 10.7

For example, we downloaded jQuery 1.9.1 as jquery-1.9.1.zip. We need to install it to Maven local repository.

Here are the steps.

In MyEclipse, File -> Import, then expand Maven4MyEclipse, select Install or deploy an artifact to a Maven repository.

Browse... to enter the jquery-1.9.1.zip into the Artifact file field.

Leave POM file empty, leave Generate POM and Create Checksum as checked.

Set Group Id as org.jquery.

Set Artifact Id as core.

Set Version as 1.9.1.

Set Packaging as zip.

Leave Classifier empty.

Click on Finish and it is installed.

What if we don't like it and want to uninstall it?

Just change directory to C:\Users\[userid]\.m2\repository and find org\jquery\core. Remove the whole directory.

Come back to MyEclipse and go,

Preferences -> MyEclipse -> Maven4MyEclipse -> User Settings.

Then Reindex the local repository.

Friday, February 07, 2014

Continue: How the CastorMarshaller Mapping Look Like

I choose CastorMarshaller over Jaxb2Marshaller because I love what the mapping.xml gives me. It is powerful and flexible even though annotation is very cool.

I also choose not to generate the famous ObjectFactory and POJO from WSDL. Partially because I have to access a rather poor written WSDL. These generated classes bear names of non-sense and confusion. Also partially because I only need to access 20% of the web services. To bundle two sets of web services in one endpoint while knowing each set is designed for different purpose and different consumer is never a practice that I will consider in any near future.

Here is the mapping file. Note I can have any class name mapping to any soap name. And these Java classes are completely POJO.



According to CastorMarshaller documentation, ns-uri as attribute of the map-to definition promises the namespace declaration. For example, ns-prefix="myPrefix" and ns-uri="myServices" would create a SOAP request of myprefix:soaprequestname xmlns:myprefix="myServices", however, it only creates myprefix:soaprequestname xmlns:myprefix="null". For this, I don't understand why.

Continue: How WebServiceTemplate Look Like

So now we come down to the spring-ws which is relatively new to me. My goal is to access a SOAP web service and my plan is to create POJO requests and receive POJO responses by using the marshallSendAndReceive from WebServiceTemplate.

Here is how I define the beans in app2Context.xml.



You can see I let CastorMarshaller to handle marshaling and unmarshaling, which I will talk about later.

Now I would show you how the code look like.



You can see I create a WebServiceMessageCallback to handle the namespace, simply because I can't find a declarative way to get it into the SOAP XML request. If any of you know how, please let me know. Or you can confirm with me this is actually the right way to go.

This method is rather simple because I let CastorMarshaller mapping to do the heavy lifting.

Continue: How the Data Access Bean Look Like

Here is one of the data access bean.



I always choose JdbcDaoSupport over Hibernate because I can have so much more control over what I want to do with the database.

Continue: How the Controllers Look Like

Here is one of the controllers.



The myApp1Service matches the bean myApp1Service. Name matching is the most simple way of autowire.

Example: Spring-MVC Spring-JDBC Spring-WS CastorMarshaller and jQuery

This is a web application, which front end is all about jQuery, back end is Spring-MVC to provide JSON web services, and Spring-JDBC to access a relational database, and Spring-WS to access a remote SOAP web services, and CastorMarshaller to convert between Java POJO and SOAP XML.

It starts with a Maven pom.xml.



The access to the relational database and the access to the remote SOAP web services are totally parallel so I don't want any cross point between them. I set up two source folders to hold them respectively but point both output folder to src/main/webapp/WEB-INF/classes.

Now it comes to the web.xml.



As you can see, I use rest-context.xml to define the rest servlet.



This rest xml is rather simple. It simply scans two controllers packages for @Controller. But I have defined in the web.xml to delegate all app1 related spring beans to app1Context.xml and app2 to app2Context.xml which sit right at their source folders respectively.

The app1Context.xml is for accessing the relational database.



You will be wondering about where is the java:/myApp1DS. This comes to the JBoss JNDI datasource configuration. Create a xml file called myApp1-ds.xml.



You will of course first enable that JDBC driver on the JBoss, but it should be an easy walk for any JBoss guy. Then deploy the myApp1-ds.xml to the server/default/deploy folder. Remember this file name has to be -ds.xml. It rather makes JBoss look like a toy.

RESTClient to Test JSON Web Services

RESTClient is an add-on for Firefox. Once I was in a company that Firefox installation required special approval. This rule of approval alone was a prove that their CIO was below qualified.

When testing JSON web services, the only trick is to set the JSON request header.

Click on Headers and add Content-Type as name, application/json; charset=utf-8 as value.

Otherwise you will get HTTP Status 415.

Example: JBoss and LDAP

JBoss 5.1.0.GA.

1. Change directory to server/default/conf and edit login-config.xml
2. Add a new block of application-policy, I put it before the "other" application-policy.



3.Under the WEB-INF directory, create jboss-web.xml and add a jboss-web definition.



4. Edit the web.xml file and add security configurations.



5. It is nice to see what is happening behind the door, so I enable the trace in the JBoss logging configuration. Edit server/default/conf/jboss-log4j.xml.

MyEclipse Enable Maven Dependencies in the Build Path

MyEclipse Enterprise Workbench

Version: 10.7

Of course, first disable the Maven4MyEclipse.

Then enable the WTP Deprecated. (as shown below).