Backing up data in Windows!

We all need to backup our data from time to time, be it project, personal or even miscellaneous. And, I’m no exception either! So here I was routinely taking backups using the customary Ctrl+C, Ctrl+V (Copy, Paste) in Windows, and then from nowhere an idea of an automatic script popped up, but it wasn’t long, before my indolent-self gave up seeing the amount of googling I would have to do in order to come up with something-even-remotely-working, as my scripting skills are no better than a 4 year old’s! But, somehow I stood up against all odds (Lol) and the rest was history!

The things which you’ll need:-

  1. 7-Zip
  2. Windows Vista or above (it means Windows 7 ;) )

The following is the script which not only takes the backup but also compresses it. That’s what I call efficient programming! :D

And if you thought, it was only enough, you also get a log file containing all the details of the copy operation, absolutely free! :)


@ECHO OFF

REM Script to backup the data.
 REM Author - Ankeet Maini
 REM Last Updated - 23rd April, 2012
 REM Minimum requirements: Windows Vista and above, 7-Zip

ECHO Starting back-up process.
 ECHO Copying files...

REM robocopy is the Windows Robust File Copy Command
 REM robocopy[Syntax] <source> <destination> [options]
 REM Source folder = "D:\Project\Dummy"
 REM Destination folder = "D:\Backups\Project-Backup-%date%"

robocopy "D:\Project\Dummy" "D:\Backups\Project-Backup-%date%"  /e /v /np /log+:"D:\BackupLogs.txt"

ECHO Files copied.
 ECHO Compressing the backup data using 7-Zip...

START "Compressing the backup..." /wait "C:\Program Files\7-Zip\7z.exe" a -tzip -r -mx5 "D:\Backups\Project-Backup-%date%" "D:\Backups\Project-Backup-%date%"

ECHO Data is compressed.
 ECHO Cleaning up...

RMDIR /S /Q "D:\Backups\Project-Backup-%date%"

ECHO Finished cleaning, and backing up.

All you need to do is to change the SOURCE, DESTINATION, Log file and 7-Zip folders’ paths and you’re good to go. The above script copies the data and puts it to the destination path while appending the current system date to the folder name for easy restoration later!

To actually execute the script, copy paste the above code in a notepad, and change the extension to .bat, run the batch file after altering the source folder(of which you want to take the backup), destination folder(the place where you want to save the backup) and you’re done!

You can check the log file in case something went awry. You can even go a step further and schedule it in Windows scheduler to make it run automatically on a specified date and time.

So try it out, and if you stumble across something even better, do let me know!

Posted in Tutotials, Uncategorized | 6 Comments

Binding date in Spring!

Almost often, we have a situation that a Date field is a part of our domain object. And we rely on Spring for binding this domain object with the view so as to minimize the hassles of dealing with the fields individually, and then setting them in the object in controller.

Let’s suppose we have a domain entity, Book, which has some customary fields (along with the dreaded field Date too) shown in the form below.

So lets now try our luck filling this form. So, there we go.

But, binding date isn’t that straightforward. If you ever tried to bind the date, you must have inevitably got the following error message:

Failed to convert property value of type java.lang.String to required type java.util.Date for property date; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property date: no matching editors or conversion strategy found

And even if you by passed the bean validation, your Controller would return a null for the corresponding date field.

Well, there are two easy solutions.

First: Very Easy Solution

This doesn’t asks you to do anything in your code, but limits your input to a date, whose separators should only and only be ‘/’. E.g. dd/MM/yyyy , yyyy/MM/dd, yyyy/MMM/dd

So, now filling the above information by using “/” as separators and submitting the page.

So this was the first solution.

Second: Easy Solution (Using InitBinder)

This method gives you the freedom, to get your date input in whichever format you like, and with whatsoever separators you desire.

All you need to do is to place this code-snippet in your Controller.


@InitBinder
public void initBinder(WebDataBinder webDataBinder) {
 SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
 dateFormat.setLenient(false);
 webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
 }

With this you specify to the Container that you’ll be inputting the date in this very format, and he will do the rest for you.

Let’s try a very bizarre format, dd==MMM==yyyy

To accommodate this above format, change the format declared in InitBinder,


@InitBinder
public void initBinder(WebDataBinder webDataBinder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd==MM==yyyy");
dateFormat.setLenient(false);
webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}

Filling in the form with our new date format.

Lets see if it passes the litmus test on submitting the page.

Bingo it did! And all we did was to change the format in Controller, so you can set any format and be assured, you won’t get any ugly surprises(exceptions!).

Download Source Code

You can download the source code from here

Posted in Uncategorized | Tagged , , , , | 2 Comments

Aspect Oriented Programming (AOP) with Spring!

Aspect Oriented Programming complements OOP, by making the code more Object Oriented. It helps remove the unwanted parts of code from within a function or a module.

Let’s take the most mundane example of a bank transaction. Suppose you have two accounts A and B, and you want to transfer some amount (say Rs.100) from A -> B.

So your pseudo code will consist of

A = A - 100
B = B + 100.

That’s it. But is it so? Won’t you have some logging in between, if god forbids something bad happens?

So your pseudo code will now look like this,

log("Transferring Rs. 100 from A -> B")
log("Deducting from A")

A = A - 100 

log("Deducted from A")
log("Adding to B")

B = B + 100

log("Added to B")
log("Transaction completed successfully")

Did you notice all these log statements cluttering up the actual business logic?

What if, you could just skip these and still got your logging done?

What if, you could write these in a place altogether different from your business-logic-function, which could start automatically?

This is what AOP gives us. It takes away all the cross cutting concerns from the main business logic, which otherwise would look much abstruse and sometimes extraneous as well.

In AOP, there’re certain technical jargons which at first may seem confounding, but not anymore, huh!

1. Joinpoint -> They are the triggers for the Aspects to run. Joinpoint is a point during the execution of a program. It can be a method execution, or handling some exception. But, in Spring AOP the joinpoint is always a method execution.

2. Pointcut -> Pointcut is the expression or the predicate which matches a Joinpoint triggering the advice to run. It matches the joinpoint, like execution of a method, and then fires up the advice.

3. Advice -> It’s the action that takes place after a pointcut matches the joinpoint. Advice can be of different types, “After”, “Around”, Before” etc. The advice contains the code which we want to execute on the execution of our business logic.

So let’s get our hands dirty with  coding. We’ll make a quite simple sample app.

You don’t have to copy paste, the source code is hosted on Google Codes.

Download Source Code.

1. Create the project directory structure

Type the below command in the command prompt in one line:

mvn archetype:create -DgroupId=ankeet.spring.aop -DartifactId=spring-aop-sample

Now navigate to the the project directory and execute the following command, to import the project to STS/Eclipse. Or, you can import as Existing Maven Projects too.

mvn eclipse:eclipse

Import now into STS/Eclipse as existing projects.

Delete the test folders and the App.java as shown above.

Add a new source folder named src/main/resources. 

Your directory structure should now look like this.

2. Create two packages in the src/main/java folder:

ankeet.spring.business –> This will contain the business logic which we want to be pure business, ankeet.spring.tester –> It’ll contain the main() to run the program. And we already have a package ankeet.spring.aop –> which will contain the AOP aspect, and will get triggered when the business logic will run.

So we will have the AOP code separated from business logic.

2. In the ankeet.spring.business package create a new class 

BusinessLogic.java

package ankeet.spring.business;

public class BusinessLogic {
	public void iDontKnowAboutAspects() {
		System.out.println("Start of function.");
		System.out.println("This is a Dummy function.");
		System.out.println("End of function.");
	}
}

3. In the ankeet.spring.aop package create a new class

AOPAspect.java

/**
 *
 */
package ankeet.spring.aop;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
 * @author ankeet
 *
 */
@Aspect
public class AOPAspect {

 @Pointcut("execution(* *.*(..))")
 public void aspectOperations(){}

 @Before("aspectOperations()")
 public void before(JoinPoint joinPoint) {
 System.out.println();
 System.out.println("#######################Before Advice START########################");
 System.out.println("The method ->" + joinPoint.getSignature().getName() + "() begins.");
 System.out.println("The details of the method are as follows:-");
 System.out.println("Method kind : " + joinPoint.getKind());
 System.out.println("Signature declaring type : " + joinPoint.getSignature().getDeclaringTypeName());
 System.out.println("Signature name : " + joinPoint.getSignature().getName());
 System.out.println("Arguments : " + Arrays.toString(joinPoint.getArgs()));
 System.out.println("Target class : " + joinPoint.getTarget().getClass().getName());
 System.out.println("This class : " + joinPoint.getThis().getClass().getName());
 System.out.println("########################Before Advice END#########################");
 System.out.println();
 }

 @After("aspectOperations()")
 public void after(JoinPoint joinPoint) {
 System.out.println();
 System.out.println("#######################After Advice START########################");
 System.out.println("The method ->" + joinPoint.getSignature().getName() + "() ends.");
 System.out.println("The details of the method are as follows:-");
 System.out.println("Method kind : " + joinPoint.getKind());
 System.out.println("Signature declaring type : " + joinPoint.getSignature().getDeclaringTypeName());
 System.out.println("Signature name : " + joinPoint.getSignature().getName());
 System.out.println("Arguments : " + Arrays.toString(joinPoint.getArgs()));
 System.out.println("Target class : " + joinPoint.getTarget().getClass().getName());
 System.out.println("This class : " + joinPoint.getThis().getClass().getName());
 System.out.println("########################After Advice END########################");
 System.out.println();
 }
}

This aspect basically consists of a lot of System.out.println() statements to show the details of the method which it can access. So don’tget confused with all these println-s cluttering up!
4. Now write the main method to test our application.

Tester.java


/**
 *
 */
package ankeet.spring.tester;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import ankeet.spring.business.BusinessLogic;
/**
 * @author ankeet
 *
 */
public class Tester {

 public static void main(String[] args) {
 //Loading "AOP.xml"
 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("AOP.xml");
 //Getting bean from the application context.
 BusinessLogic businessLogic = (BusinessLogic) applicationContext.getBean("businessLogic");
 //Calling the function -> iDontKnowAboutAspects()
 businessLogic.iDontKnowAboutAspects();
 }
}

6. Now write the bean file AOP.xml, and put it into the src/main/resources folder.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
 <aop:aspectj-autoproxy />

 <bean id="businessLogic" class="ankeet.spring.business.BusinessLogic"/>
 <bean id="aOPAspect" class="ankeet.spring.aop.AOPAspect"/>

</beans>

This file declares the beans for the Container, so that it can instantiate when you ask for them, that’s what IoC, and DI are all about!

7. So, we’re all done except for declaring the dependencies. So, there we go, our POM file.

pom.xml


<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>ankeet.spring.aop</groupId>
 <artifactId>spring-aop-sample</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>
 <name>spring-aop-sample</name>
 <url>http://maven.apache.org</url>
 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>
 <dependencies>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>3.1.0.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>cglib</groupId>
 <artifactId>cglib-nodep</artifactId>
 <version>2.2.2</version>
 </dependency>
 <dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.6.12</version>
 </dependency>
 <dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjrt</artifactId>
 <version>1.6.12</version>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>3.8.1</version>
 <scope>test</scope>
 </dependency>
 </dependencies>
</project>

Your final directory structure should look like this.

The output of the application in the console looks like this!

So, this is all, just download the project and run the Tester.java as Java Application, and you can see the output.

That’s all folks for this post, have fun!

Posted in Tutorials | Tagged , , , , , , | 3 Comments

Knowing the dependencies amongst your jars.

It may happen often that we include a bunch of jar files in our project, but not sure about their usage. We do it many a times as we want to avoid any unforseen errors, and most of the times just for saving time’s sake which we have to spend examining each’s utility.

I too did the same, until yesterday when I intentionally started removing the jars whose utility I couldn’t directly see, and there awaited a lot of surreal surprises, and of course a plethora of errors, which I don’t normally see, all because of an inquisitive idea!

This post will again extol maven. There were days when I would just loath this word, for it required me to change my directory structure and write an additional file, POM. But gone are those days, and my ignorance about it.

Let’s take a sample POM.


<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>ankeet.spring.aop</groupId>
 <artifactId>spring-aop-sample</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>
 <name>spring-aop-sample</name>
 <url>http://maven.apache.org</url>
 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>
 <dependencies>
<dependency>
 <groupId>cglib</groupId>
 <artifactId>cglib-nodep</artifactId>
 <version>2.2.2</version>
 </dependency>
 <dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.6.12</version>
 </dependency>
 <dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjrt</artifactId>
 <version>1.6.12</version>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>3.8.1</version>
 <scope>test</scope>
 </dependency>
 </dependencies>
</project>

Now when I save it in STS, the maven plugin downloads these dependencies and adds them to my classpath.

So, no surprise there, four dependency declarations and four dependencies listed above.

Now, add one more dependency to your POM and save it.

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>3.1.0.RELEASE</version>
 </dependency>

We just added a spring-context dependency to our project. Now we’ll see the dependencies included in the project with the inclusion of this new one.

What in the world???

We just included one single dependency!!

From where have all these come from?

It’s okay, don’t panic there’s no error, or virus for that matter. :)

By now you must have guessed, these extra jars are the dependencies of spring-context dependency. Spring-context depends on them directly or indirectly, so you have to include all those in your classpath but if use maven, it’ll do it automatically for you. :)

To know it in a more detailed manner, type

mvn dependency:tree

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building spring-aop-sample 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ spring-aop-sample ---
[INFO] ankeet.spring.aop:spring-aop-sample:jar:1.0-SNAPSHOT
[INFO] +- org.springframework:spring-context:jar:3.1.0.RELEASE:compile
[INFO] | +- org.springframework:spring-aop:jar:3.1.0.RELEASE:compile
[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] | +- org.springframework:spring-beans:jar:3.1.0.RELEASE:compile
[INFO] | +- org.springframework:spring-core:jar:3.1.0.RELEASE:compile
[INFO] | | \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] | +- org.springframework:spring-expression:jar:3.1.0.RELEASE:compile
[INFO] | \- org.springframework:spring-asm:jar:3.1.0.RELEASE:compile
[INFO] +- cglib:cglib-nodep:jar:2.2.2:compile
[INFO] +- org.aspectj:aspectjweaver:jar:1.6.12:compile
[INFO] +- org.aspectj:aspectjrt:jar:1.6.12:compile
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.297s
[INFO] Finished at: Tue Dec 20 11:32:02 IST 2011
[INFO] Final Memory: 5M/15M
[INFO] ------------------------------------------------------------------------

So you can see how spring-context is dependent on spring-aop and spring-aop inturn is dependent on aopalliance.

There are several other useful goals of this maven dependency plugin like analyze. You can check them here.

I hope you’ll too have fun discovering the very jars you unknowingly used and their obscurely hidden interdependencies. :)

Posted in Uncategorized | Tagged , , | 2 Comments

Managing Maven and it’s versions. Made Easy!

Maven is a fantastic tool for building Java codes, and makes the process very easy and efficient. The dependency management in Maven is done by just declaring them along with the version numbers. Sometimes, managing different versions becomes extremely tedious, as it involves searching the corresponding element in POM and then changing the version number if you need to upgrade it.

When creating new projects using maven-archetypes, although it generates the POM automatically, with the basic minimum dependencies declared along with the information of plugins, but sometimes misses their versions, which makes it highly susceptible to build errors, and can also lead to total build failure if it’s built with newer versions of Apache Maven.

Let’s just quickly see a scenario like above. We’ll create the project using maven-archetypes and maven itself will give us near fatal warnings when we try to compile it :)

Type this in your command prompt, in one single line.

mvn archetype:create -DarchetypeGroupId=org.springframework.ws -DarchetypeArtifactId=spring-ws-archetype -DarchetypeVersion=2.0.1.RELEASE -DgroupId=version.demo -DartifactId=version-demo

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-archetype-plugin:2.1:create (default-cli) @ standalone-pom ---
[WARNING] This goal is deprecated. Please use mvn archetype:generate instead
[INFO] Defaulting package to group ID: version.demo
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: spring-ws-archetype:2.0.1.RELEASE
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: version.demo
[INFO] Parameter: packageName, Value: version.demo
[INFO] Parameter: package, Value: version.demo
[INFO] Parameter: artifactId, Value: version-demo
[INFO] Parameter: basedir, Value: F:\
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: F:\version-demo
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.455s
[INFO] Finished at: Fri Dec 16 00:13:12 IST 2011
[INFO] Final Memory: 6M/11M
[INFO] ------------------------------------------------------------------------

Now, you have the project, go to the root, and do an mvn compile

[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for version.demo:version-demo:war:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 14, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building version-demo Spring-WS Application 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ version-demo ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ version-demo ---
[INFO] No sources to compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.974s
[INFO] Finished at: Fri Dec 16 00:16:59 IST 2011
[INFO] Final Memory: 2M/6M
[INFO] ------------------------------------------------------------------------

So, did you see the warnings?

And we did nothing wrong, created the project from maven-archetype, and then simply compiled it. But due to the missing versions of the plugins, we see these warnings. This is a small POM but in a big project, the POM may be very large, so manual finding of these and rectifying seems an uphill task.

Enter mvn versions plugin – The Panacea for you :)

Type in mvn versions:display-plugin-updates

[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for version.demo:version-demo:war:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 14, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building version-demo Spring-WS Application 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- versions-maven-plugin:1.2:display-plugin-updates (default-cli) @ version-demo ---
[INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from central
[INFO]
[INFO] All plugins with a version specified are using the latest versions.
[INFO]
[WARNING] The following plugins do not have their version specified:
[WARNING] maven-compiler-plugin .................................. (unknown)
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.742s
[INFO] Finished at: Fri Dec 16 00:27:23 IST 2011
[INFO] Final Memory: 5M/10M
[INFO] ------------------------------------------------------------------------

So it will tell you whose versions you have missed and you can change easily. I’ll update the version to 2.3.2, after I looked it up at http://mirrors.ibiblio.org/. It’ll also tell you which dependency has a new version available also. Just type in the following to check your dependencies.

mvn versions:display-dependency-updates

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building version-demo Spring-WS Application 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- versions-maven-plugin:1.2:display-dependency-updates (default-cli) @ version-demo ---
[INFO] No dependencies in Dependencies are using the newest version.
[INFO]
[INFO] The following dependencies in Dependencies have newer versions:
[INFO] org.springframework.ws:spring-ws-core ...
[INFO] 2.0.1.RELEASE -> 2.0.3.RELEASE
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.900s
[INFO] Finished at: Fri Dec 16 00:41:46 IST 2011
[INFO] Final Memory: 5M/10M
[INFO] ------------------------------------------------------------------------

It doesn’t stop here, it even goes a step further and changes your POM to use all the latest versions. All you have to do is

mvn versions:use-latest-versions and voila you’re done!

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building version-demo Spring-WS Application 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- versions-maven-plugin:1.2:use-latest-versions (default-cli) @ version-demo ---
[INFO] Updated org.springframework.ws:spring-ws-core:jar:null:2.0.1.RELEASE to version 2.0.3.RELEASE
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.096s
[INFO] Finished at: Fri Dec 16 00:42:55 IST 2011
[INFO] Final Memory: 5M/10M
[INFO] ------------------------------------------------------------------------

You can dig more into this plugin at it’s official site. It’s of great help, but only lesser known.

That’s all for this one. Happy versioning  :)

Posted in Uncategorized | Leave a comment

Spring Web Services Client

In this post we’ll develop a Spring WebService client which will consume the Webservice we created in the previous post, getSquareService. This getSquareService takes in an integer as an input and gives back its square via http using spring web services 2.0. Earlier we used a Soap UI, to test and send/recieve our request/response, but now we’ll develop our own client as in real applications.

This client will be a normal Spring MVC application. As far as content is concerned, we’ll use two things here:-

  1. Web Service Template by Spring: This web service templates, makes our client code, extremely easy and good. It’s a helper template just as in JDBCTemplate, which is to access database using jdbc.
  2. wsimport tool by JAX-WS: This tool, takes in the wsdl url, and generates the Java Proxy classes and other artifacts which are necessary to consume the webservice.

Let’s start developing our client to the webservice. You don’t have to copy paste, the source code is shared and can be downloaded easily.

Download source code.

You can see the older version from here. The current version incorporates the changes required to comply with Maven 3

Now, since you have the source code at your disposal, let’s start it from the very beginning :)

Developing the Web Service Client from scratch!

1. Download the webservice project created in the earlier post Spring Web Services 2. Made Easy! and import it using Existing Maven Projects in your STS/Eclipse. (I use SpringSourceToolSuite, STS in short, though!)

2. Now open up your browser and type in the following URL to see the WSDL generated and examine it.

http://localhost:8080/spring-ws2-exemplary/getSquare.wsdl

3. Download the wsimport tool and execute it by following the instructions and set the path of it’s bin folder in your classpath.

4. Now we’ll use wsimport tool to generate our Java classes, as we generated it for jaxb.

5. Open command prompt and enter the following command to generate the classes at some place.

wsimport -d F:\generated -keep http://localhost:8080/spring-ws2-exemplary/getSquare.wsdl

Make sure the target directory already exists. Below is the screeen shot of this command.

Now check at the target place for the files generated, F:\Generated in my case.

6. Create the project by executing the following command in a single line.

mvn archetype:generate -DgroupId=ankeet.ws2.client -DartifactId=spring-ws2-client -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

7. Open your STS/Eclipse and import the above as Existing Maven Projects. This import option will come only if you have maven plugin installed for your IDE. With STS it comes in built, but you need to install it explicitly for Eclipse. Else do an mvn eclipse:eclipse and then import as Existing Projects in workspace.

8. Create a new source folder and in it a package com.wordpress.ankeetmaini.spring_ws2_square and copy all the .java files created earlier by wsimport.

9. Create another package ankeet.spring.ws2.controller, where we’ll create the Controller of our Client App. Call it ClientController.java

/**</pre>
 *
 */
package ankeet.spring.ws2.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ws.client.core.WebServiceTemplate;

import com.wordpress.ankeetmaini.spring_ws2_square.ObjectFactory;
import com.wordpress.ankeetmaini.spring_ws2_square.SquareServiceRequest;
import com.wordpress.ankeetmaini.spring_ws2_square.SquareServiceResponse;

/**
 * @author Ankeet Maini
 *
 */
@Controller
@RequestMapping("/")
public class ClientController {
 @Autowired
 private WebServiceTemplate webServiceTemplate;

 /**
 * This is the default handler. When application goes live
 * the control comes to this, and it fires a JSP,
 * asking the input.
 */
 @RequestMapping(method = RequestMethod.GET)
 public String getRequest(Model model) {
 model.addAttribute("squareServiceRequest", new ObjectFactory().createSquareServiceRequest());
 //Show request.jsp
 return "request";
 }

 /**
 * This is the handler, which takes in the input number, and calculates
 * the square by taking it from the webservice, via WebServiceTemplate, and then finally
 * sets as a ModelAttribute, which in turn is shown by "response.jsp"
 */
 @RequestMapping(method = RequestMethod.POST)
 public String showResponse(@ModelAttribute SquareServiceRequest squareServiceRequest, Model model) {
 //Creating the SquareServiceResponse object.
 SquareServiceResponse squareServiceResponse = new ObjectFactory().createSquareServiceResponse();
 //Sending the request object via WebServiceTemplate and getting back the response from WebService :)
 squareServiceResponse = (SquareServiceResponse) webServiceTemplate.marshalSendAndReceive(squareServiceRequest);
 //This was supposed to be a hard part. Piece of cake :)
 model.addAttribute("squareServiceResponse", squareServiceResponse);
 //Show response.jsp
 return "response";
 }

}
<pre>

10. Create a folder “views” inside WEB-INF to keep your JSP files. Inside the “views” folder create two JSP files:

  1. request.jsp    -> This will ask user a number whose square is to be calculated using WebService: getSquare.
  2. response.jsp -> This will show the user calculated square, which came in response from getSquare webservice.

request.jsp


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page session="false" %>

<html>
<head>
<%@ page isELIgnored="false" %>
<title>Square Webservice 2 Client</title>
</head>
<body>
 <form:form commandName="squareServiceRequest" method="post">
 <table>
 <tr>
 <td>Enter Number:</td>
 <td><form:input path="input"/></td>
 <td><font color="red"><form:errors path="input"/></font></td>
 </tr>
 </table>
 <input name="submit" type="submit" value="Get it's square!" />
 </form:form>
</body>
</html>

response.jsp


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<%@ page isELIgnored="false" %>
<title>Square Webservice 2 Client</title>
</head>
<body>
 The square of the entered number is: <b><font color="red" size="3">${squareServiceResponse.output}</font></b>
 <br />
 <br /> This is brought to you by <i>Spring Webservices 2</i> and <font color="blue" size="4.5"><b>Ankeet Maini</b></font> :)
</body>
</html>

11. Define your web.xml. Make sure web.xml is directly inside the WEB-INF.


<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
 <display-name>Archetype Created Web Application</display-name>
 <servlet>
 <servlet-name>spring-ws2-client</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
 <servlet-name>spring-ws2-client</servlet-name>
 <url-pattern>/</url-pattern>
 </servlet-mapping>
</web-app>

12. Create your spring-ws2-client-servlet.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:sws="http://www.springframework.org/schema/web-services"
 xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd
 http://www.springframework.org/schema/web-services
 http://www.springframework.org/schema/web-services/web-services-2.0.xsd
 http://www.springframework.org/schema/mvc
 http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

 <!-- Activates various annotations to be detected in bean classes -->
 <context:annotation-config />

<!-- Scans the classpath for annotated components that will be auto-registered
 as Spring beans. For example @Controller and @Service. Make sure to set the
 correct base-package -->
 <context:component-scan base-package="ankeet.spring" />
 <context:component-scan base-package="com.wordpress" />

<!-- Configures the annotation-driven Spring MVC Controller programming
 model. Note that, with Spring 3.0, this tag works in Servlet MVC only! -->
 <mvc:annotation-driven />
 <!-- Declare a view resolver -->
 <bean id="viewResolver"
 class="org.springframework.web.servlet.view.InternalResourceViewResolver"
 p:prefix="/WEB-INF/views/" p:suffix=".jsp" />

 <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate"
 p:marshaller-ref="jaxbMarshaller"
 p:unmarshaller-ref="jaxbMarshaller"
 p:defaultUri="http://localhost:8080/spring-ws2-exemplary/squareService"
 p:messageSender-ref="messageSender">
 <constructor-arg ref="messageFactory"/>
 </bean>
 <bean id="messageSender" class="org.springframework.ws.transport.http.CommonsHttpMessageSender"/>
 <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
 <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"
 p:contextPath="com.wordpress.ankeetmaini.spring_ws2_square"/>

</beans>

13. Lastly, define your POM.xml file so that maven can provide for all your dependencies.


<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">
 <modelVersion>4.0.0</modelVersion>
 <groupId>ankeet.ws2.client</groupId>
 <artifactId>spring-ws2-client</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>spring-ws2-client Maven Webapp</name>
 <url>http://maven.apache.org</url>
 <dependencies>
 <dependency>
 <groupId>javax.xml.bind</groupId>
 <artifactId>jaxb-api</artifactId>
 <version>2.0</version>
 </dependency>
 <dependency>
 <groupId>com.sun.xml.bind</groupId>
 <artifactId>jaxb-impl</artifactId>
 <version>2.0.3</version>
 </dependency>
 <dependency>
 <groupId>org.apache.xmlbeans</groupId>
 <artifactId>xmlbeans</artifactId>
 <version>2.4.0</version>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>3.8.1</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-beans</artifactId>
 <version>3.0.5.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>3.0.5.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context-support</artifactId>
 <version>3.0.5.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.ws</groupId>
 <artifactId>spring-ws-core</artifactId>
 <version>2.0.3.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-web</artifactId>
 <version>3.0.5.RELEASE</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>3.0.5.RELEASE</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <version>1.2.14</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-tx</artifactId>
 <version>3.0.5.RELEASE</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>jstl</groupId>
 <artifactId>jstl</artifactId>
 <version>1.1.2</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>taglibs</groupId>
 <artifactId>standard</artifactId>
 <version>1.1.2</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-webmvc</artifactId>
 <version>3.0.5.RELEASE</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-aop</artifactId>
 <version>3.0.5.RELEASE</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>

<dependency>
 <groupId>commons-httpclient</groupId>
 <artifactId>commons-httpclient</artifactId>
 <version>3.1</version>
 <type>jar</type>
 <scope>compile</scope>
 </dependency>
 </dependencies>
 <build>
 <finalName>spring-ws2-client</finalName>
 </build>
</project>

14. Check your directory structure. Make sure you are not missing anything, neither the resource, nor the structure.

15. To run this web client, first run the webservice, spring-ws2-exemplary project, download it from here.

16. Run the client now. The project is hosted on google codes. Download it from here. Now, run the client by importing it as Existing Maven Projects.

Enter the number, and press the button.

That’s all folks. If you come across any problem, do let me know, and if you do go a step further and do some improvements then do share it here, and I’ll incorporate into the post citing your name and contribution. :)

Posted in spring, Tutorials | Tagged , , , , , | 5 Comments

Spring Web Services 2. Made easy!

We’ll see how to develop Spring Webservices 2, along with validation on the base of xml schema. We’ll use spring-ws 2, maven, jaxb for making this sample project spring-ws2-exemplary. 

Source Code!

You don’t need to copy paste the code, it’s available for download at the bottom of the page. The project may give some errors while building due to non-conformance of Maven 3, so for that I’ve enhanced the POM and you can download the new project from here.

We’ll see the whole process in easy steps, making no big dragon of this!

1. I presume you are probably aware of maven. Setting it up is easy. If you’re not a maven-compatriot, don’t worry, google it, and you’ll have it up and running in a matter of mins.

So all said and done, lets start the development rightaway.

2. Open command prompt and navigate to your workspace location, or wherever you need to make the project.

3. Type in the following command, all in one line.

mvn archetype:create -DarchetypeGroupId=org.springframework.ws -DarchetypeArtifactId=spring-ws-archetype -DarchetypeVersion=2.0.1.RELEASE -DgroupId=ankeet.spring.ws2 -DartifactId=spring-ws2-exemplary

So there you have the basic skeleton of the project ready for you, including the spring config files, pom.xml and the requisite folder structure. Go have look ;)

4. Now you have the basic structure with you, but it still doesn’t qualifies to be imported as a project in eclipse or SpringsourceToolSuite (STS), as it lacks the .classpath and .project files.

To overcome, go to the project folder spring-ws2-exemplary in this case and run the following command:-

mvn eclipse:eclipse

Now you can import this as Existing Projects into Workspace

5. Creating the xml request and response messages. We’ll create a service SquareService, which will give the square of the input number.

So our request will be

        <SquareServiceRequest>
	   <Input>3</Input>
	</SquareServiceRequest>

and response will be

       <SquareServiceResponse>
	  <Output>9</Output>
       </SquareServiceResponse>

6. Since, you now have the request and response messages combine it into one xml file and generate the xsd.

Combining the request and response in a file spring-ws2-square.xml

<?xml version="1.0" encoding="UTF-8"?>
<SquareService xmlns="http://ankeetmaini.wordpress.com/spring-ws2-square">

	<SquareServiceRequest>
		<Input>3</Input>
	</SquareServiceRequest>

	<SquareServiceResponse>
		<Output>9</Output>
	</SquareServiceResponse>

</SquareService>

7. To generate the xsd, you can use trang.jar if you don’t have anything else. Its an open source product.

Download the latest version and unzip it on your system. Open command prompt and navigate to the unzipped folder.

To create the XSD run the following command:

java -jar trang.java <Path-of-XML-file> <Path-where-xsd-is-to-be-generated>

I copied my xml to the trang direcotory only, and generated my corresponding xsd there too, and then copied it to WEB-INF. Simple.

So you have the xsd generated in the current directory. Before putting it into use, we need to tweak it a little bit to suit our purposes.

Original spring-ws2-square.xsd


<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://ankeetmaini.wordpress.com/spring-ws2-square" xmlns:s="http://ankeetmaini.wordpress.com/spring-ws2-square">
  <xs:element name="SquareService">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="s:SquareServiceRequest"/>
        <xs:element ref="s:SquareServiceResponse"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="SquareServiceRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="s:Input"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="Input" type="xs:integer"/>
  <xs:element name="SquareServiceResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="s:Output"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="Output" type="xs:integer"/>
</xs:schema></pre>

Editing it, we get the final xsd. Please note the finer details yourself, and try to comprehend. You’ll be able to figure out the need to edit it most of the times for the sake of more conciseness, and removal of extraneous elements, if you know what I mean ;)

Final spring-ws2-square.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://ankeetmaini.wordpress.com/spring-ws2-square" xmlns:s="http://ankeetmaini.wordpress.com/spring-ws2-square">

  <xs:element name="SquareServiceRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Input" type="xs:integer"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="SquareServiceResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Output" type="xs:integer"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

Now copy this to the src/main/webapp/WEB-INF folder, so that it’ll be detected at classpath.

8. Open web.xml located in WEB-INF folder and change the name of the servlet to spring-ws2 (This is not required but I do, to remove the ambiguity, if at all it arises). Don’t forget to change in the <servlet-maping> also.

Add an init param

<init-param>
			<param-name>transformWsdlLocations</param-name>
			<param-value>true</param-value>
		</init-param>

Verify your web.xml looks like this:-

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">

    <display-name>Archetype Created Web Application</display-name>

 	<servlet>
		<servlet-name>spring-ws2</servlet-name>
		<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>transformWsdlLocations</param-name>
			<param-value>true</param-value>
		</init-param>
	</servlet>

    <servlet-mapping>
        <servlet-name>spring-ws2</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

9. Now, since you changed the servlet’s name, you need to change the Spring’s configuration file too, because the container will look for <servlet-name>-servlet.xml

Rename (or better Refactor) it to spring-ws2-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:sws="http://www.springframework.org/schema/web-services"
       xsi:schemaLocation="http://www.springframework.org/schema/beans	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
	   http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/web-services                      	http://www.springframework.org/schema/web-services/web-services-2.0.xsd">

    <!-- To detect @Endpoint -->
<sws:annotation-driven/>

<!-- To detect @Service, @Component etc -->
<context:component-scan base-package="ankeet.spring" />

    <!-- To generate dynamic wsdl -->
	<sws:dynamic-wsdl
		id="getSquare"
		portTypeName="SquareService"
		locationUri="/squareService"
		targetNamespace="http://ankeetmaini.wordpress.com/spring-ws2-square">
		<sws:xsd location="/WEB-INF/spring-ws2-square.xsd"/>
	</sws:dynamic-wsdl>

    <!-- For validating your request and response -->
    <!-- So that you don't send a string instead of an integer -->

	 <sws:interceptors>
<bean id="validatingInterceptor"
        class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
    <property name="schema" value="/WEB-INF/spring-ws2-square.xsd"/>
    <property name="validateRequest" value="true"/>
    <property name="validateResponse" value="true"/>
</bean>
  </sws:interceptors>

</beans>

10. In Eclipse/STS right click your project and and then new, and select a new source folder and name it as src/main/java

Create three packages : ankeet.spring.ws2.endpoint, ankeet.spring.ws2.service, ankeet.spring.ws2.generated

11. Since we’re using jaxb for converting xml <—> object, we need to make changes to the pom.xml to add its dependencies and plugins, so that the Java Classes are generated at compile time from the XSD given.

Add the following piece of code to the pom in the <plugins> section

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>jaxb2-maven-plugin</artifactId>
  <executions>
    <execution>
      <goals>
	<goal>xjc</goal>
      </goals>
     </execution>
   </executions>
  <configuration>
    <schemaDirectory>src/main/webapp/WEB-INF/</schemaDirectory>
  </configuration>
</plugin>

Similarly add the dependencies in the <dependencies> section of POM.

<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-impl</artifactId>
  <version>2.0.3</version>
</dependency>
<dependency>
  <groupId>org.apache.xmlbeans</groupId>
  <artifactId>xmlbeans</artifactId>
  <version>2.4.0</version>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.8.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <scope>compile</scope>
  <version>1.2.16</version>
</dependency>

11. Write the endpoint class as follows:-

SquareWSEndpoint.java

/**
 *
 */
package ankeet.spring.ws2.endpoint;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;

import ankeet.spring.ws2.generated.*;
import ankeet.spring.ws2.generated.SquareServiceResponse;
import ankeet.spring.ws2.service.SquareService;

/**
 * @author Ankeet Maini
 *
 */
@Endpoint
public class SquareWSEndpoint {
	//To calculate square of the input.
	@Autowired
	private SquareService squareService;
	//This is like @RequestMapping of Spring MVC
	@PayloadRoot(localPart="SquareServiceRequest", namespace="http://ankeetmaini.wordpress.com/spring-ws2-square")
	@ResponsePayload
	public SquareServiceResponse getSquare(@RequestPayload SquareServiceRequest request) {
		SquareServiceResponse response = new ObjectFactory().createSquareServiceResponse();
		response.setOutput(squareService.square(request.getInput()));
		return response;
	}
}

12. Now write the service classes which will actually do the squaring.

SquareService.java

package ankeet.spring.ws2.service;

import java.math.BigInteger;

public interface SquareService {
	public BigInteger square(BigInteger bigInteger);

}

And it’s implementation class SquareServiceImpl.java

package ankeet.spring.ws2.service;

import java.math.BigInteger;

import org.springframework.stereotype.Service;

@Service
public class SquareServiceImpl implements SquareService {

	public BigInteger square(BigInteger bigInteger) {
		return (bigInteger.multiply(bigInteger));
	}

}

13. Now when you clean your project JAXB will create the classes from the XSD present on the classpath, in our case spring-ws2-square.xsd located in WEB-INF. The code generated will be in the target folder, so you’ll have to copy the files and put into the ankeet.spring.ws2.generated package, and correct the inconsistencies arising in the package names by shifting. Also, make src/main/webapp a source folder(By navigating to webapp and then right clicking and in Configure Buildpath, make it a source folder).

14. After this your project structure should prcisely look like this.

15. To run the project you can create a war and deploy on the server, or use maven. Go the project directory and type the following command to run the project on tomcat server:

mvn tomcat:run

16. Open your web browser and enter the following url

http://localhost:8080/spring-ws2-exemplary/getSquare.wsdl to see the WSDL file generated.

17. To test the application, you can build a client or use Soap UI. To test with soap UI, open it, create an new project and give it the above url of WSDL.

Press Ok.

Click on Request1 and on the left side an interface will appear asking your request. Enter any integer and press the green button to send it to the server. If you enter anything other than an integer, a Validation error will be reported on the other side.

and if you do enter any thing else than integer, say a string, the Validation will fail and you’ll get the following error.

Just in case if you wish to know, the above Response is

<pre><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Client</faultcode>
         <faultstring xml:lang="en">Validation error</faultstring>
         <detail>
            <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-datatype-valid.1.2.1: 'a' is not a valid value for 'integer'.</spring-ws:ValidationError>
            <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: The value 'a' of element 'spr:Input' is not valid.</spring-ws:ValidationError>
         </detail>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The code is hosted on Google Codes, to download the project click here.

To run it, just unzip the file, open command prompt, navigate to the directory and type : mvn tomcat:run, and voila you’re done!

While creating this project I read a lot, and found these blogs extremely helpful,

1. Jamesbnuzzo

2. Ice09

3. krams

That’s all for this one. Enjoy building and running it. :)

Posted in Tutorials | Tagged , , , , , | 4 Comments