ICE09 . playing with java, scala, groovy and spring .

Playing with Spring

Proxying your Web Service Requests with Gradle and Groovy

Posted by ice09 on October 13, 2012

Intention

Sometimes you have to mock a Web Service request, eg. to ensure that a client works well with a new interface.
Usually, this can be done easily with soapUI in mocking Web Servide mode:

However, in this special case several Web Services had to be called, but only some of them should be intercepted, others should just be just forwarded to the actually running Web Services.

Groovy Solution

As so often, Groovy is the perfect solution for this. There are just three files involved, with these three files, together with the Gradle Quickstart plugin of the Springsource Tool Suite Grale plugin.

So, just three steps to your Groovy Proxy Server solution:

  1. Download Springsource Too Suite and the Gradle Plugin, create a Gradle Quckstart Plugin Gradle project
  2. Create the ProxyServer Groovy script and the sample response file in src/main/resources
  3. Add the application plugin as well as the groovy plugin to the Gradle build … that’s it. I’d like to say: Gradle rocks!

The main ProxyServer Groovy script

package de.ice09.blog

import static groovyx.net.http.Method.*
import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpHandler
import com.sun.net.httpserver.HttpServer
import org.apache.http.client.ResponseHandler
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.BasicResponseHandler
import org.apache.http.impl.client.DefaultHttpClient

class ProxyHttpHandler implements HttpHandler {
        def answers = []

        ProxyHttpHandler(def answers) {
                this.answers = answers
				println "prepared answers: $answers"
        }

        void handle(HttpExchange exchange) throws IOException {
                def reqText = exchange.requestBody.getText()
                def fileName = answers.find{ reqText.contains(it) }
                def response
                if (fileName != null) {
					println "...sending prepared answer: $fileName"
                    response = new File("${fileName}.xml").getText()
                } else {
                    println ">>> redirect >>>"

                    HttpPost builder = new HttpPost( "http://localhost:8088/mockGetCodeDecodeSoap12" )
                    StringEntity strent= new StringEntity(reqText);
                    strent.setContentType("application/soap+xml; charset=utf-8");
                    builder.setEntity(strent);

                    DefaultHttpClient client = new DefaultHttpClient();
                    ResponseHandler<String> responseh = new BasicResponseHandler();
                    String responseBody = client.execute(builder, responseh);
                    println(responseBody);
                    response = responseBody
                }
                exchange.sendResponseHeaders(200, response.length());
                def outout = exchange.responseBody
                outout.write(response.bytes);
                outout.close();
        }

}
def server = HttpServer.create(new InetSocketAddress(8080), 0);
def answers = []
def files = new File(".").eachFile {
	if (it.name.endsWith("xml")) {
		answers << it.name - ".xml"
	}
}
def context = server.createContext("/", new ProxyHttpHandler(answers));
server.executor = null
server.start();
println "######################\nstarted proxyserver...\n######################"

This script scans the local directory for all XML files and stores the filenames. If a requestbody is retrieved with the Java Web Server, which has somehow the filename in it’s text (this is very fuzzy, however, it worked for our problem), the prepared text file is sent back.
If no corresponding file is found, the request is forwarded to the real service and the response is “tunneled”.

So, only the build.gradle is missing, it is the original Quickstart gradle build file, extended just with the application plugin, the groovy plugin and their configurations.

So, the application can be build with gradle installApp, which creates the complete application, which should be started in the root directory with bin/gradleapp.bat. Voila!

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'
apply plugin: 'groovy'

mainClassName = "de.ice09.blog.ProxyServer"

sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

installApp {
	from 'src/main/resources'
}

dependencies {
	groovy group: 'org.codehaus.groovy.modules.http-builder', name: 'http-builder', version: '0.5.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
    systemProperties 'property': 'value'
}

Posted in Groovy | Leave a Comment »

Sample Questions for EIwS-1.x-certification-study-guide

Posted by ice09 on January 16, 2012

Currently, I am preparing for the Enterprise Integration with Spring 1.x Certification, with the Study Guide.

After having tried to google some of the questions, I had to realize that nobody did try to answer the questions (at least openly). Therefore, I will give it a try.
Please be aware that these answers are based on my unterstanding of the question topics. It is not very likely, but they may even be completely false. If they are, please tell me…

Topics by Subject Area

Remoting

General

  • The concepts involved with Spring Remoting on both server- and client-side Configuration and Exposition of Business Services declaratively (with no code changes) using exporters Support of different protocols in a consistent way: RMI, EJB, HttpInvoker, Hessian/Burlap Usage of remote Business Services transparently on client side (using proxy mechanisms with FactoryBeans) Proxy can be injected as Business Service interface, client does not know the service call is remote
  • The benefits of Spring Remoting over traditional remoting technologies No dependency on a concrete Remoting Technology (is abstracted by exception coversion and automatic proxy creation) No adherence to a particular Remoting Technology Binding etc. is done by Spring Exporters Remoting is done by Proxies generated from FactoryBeans
  • The remoting protocols supported by Spring RMI(-IIOP), Stateless EJB, HttpInvoker, Hessian/Burlap

RMI-based Spring Remoting

  • How Spring Remoting-based RMI is less invasive than plain RMI Through the use of the RmiProxyFactoryBean and the RmiServiceExporter Spring supports both traditional RMI (with java.rmi.Remote interfaces and java.rmi.RemoteException) and transparent remoting via RMI invokers (with any Java interface) Client does not have to deal with RemoteExceptions, Server does not have to extend RMI classes

Spring HTTP Invoker

  • How client and server interact with each other The HttpInvokerProxy (client) sends a POST request (transparently by calling a method invocation) to the HttpInvokerServiceExporter (server) using Java serialization (HTTP as transport protocol)

(Reference)

Web Services

General

  • How do Web Services compare to Remoting and Messaging Web Services are interoperable across several platforms. Source and Destination can change, there are no direct dependencies (as with remote method invocation (RPC)). Web Services (can) resemble Document-based messaging more than RPC with loose coupling as a result, but both styles (RPC vs. document-oriented approach) exist. Spring supports the document-oriented Contract-first approach.

Spring Web Services

  • The approach to Spring Web Service that Spring-WS supports Spring-WS uses the Contract-first approach (start with XSD/WSDL) instead of annotating pre-existing methods
  • The Object-to-XML frameworks supported by Spring-OXM JAXB1/2, Castor, XMLBeans, XStream and JiBX
  • The strategies supported to map requests to endpoints Message Payload, SOAP Action Header, WS-Adressing and XPath General Request Processing (Message Dispatcher -> Endpoint Mapping -> Endpoint Adapter -> Endpoint) PayloadRootAnnotationMethodEndpointMapping and SoapActionAnnotationMethodEndpointMapping Request -> MessageDispatcher -> EndpointMapping -> EndpointInvocationChain -> Endpoint and Interceptors
  • Of these strategies, how does @PayloadRoot work exactly? Sample: @PayloadRoot(localPart = "orderRequest", namespace = "http://samples") @ResponsePayload public Order getOrder(@RequestPayload OrderRequest orderRequest) { For this to work the PayloadRootAnnotationMethodEndpointMapping must be registered as a bean
  • The functionality offered by the WebServiceTemplate WebServiceTemplate simplifies client Web Service (SOAP) access in the usual Spring Template way (cp. JDBCTemplate, JMSTemplate) The main functionality is sending an XML Source and receiving an XML Result This functionality can be extended by the usual callback mechanisms (eg. access SOAP Header) Can use different protocols (JMS, Mail, XMPP)

Web Services Security

  • The underlying WS-Security implementations supported by Spring-WS XML Web Services and Security (http://xwss.java.net/), integration with XwsSecurityInterceptor Uses callback mechanisms and policy configuration files Integration with Spring Security (http://static.springsource.org/spring-security/site/)
  • How key stores are supported by Spring-WS for use with WS-Security Usage of KeyStoreFactoryBean (Properties password (Keystore) and location (JKS-File)) Usage of KeyStoreCallbackHandler (with private key password)

RESTFul services with Spring-MVC

General

  • The main REST principles With usage of identifiable resources, an uniform interface (GET, HEAD, PUT, POST, DELETE) is used to represent the (abstract) resources with different representations (HTML, XML, PDF, etc.). A control flow (client state transition) is introduced by using hypermedia links as return values.

REST support in Spring-MVC

  • Spring-MVC is an alternative to JAX-RS, not an implementation
  • The @RequestMapping annotation, including URI template support Sample: @Controller @RequestMapping("/edit{number}") public class EditForm { @RequestMapping(method = RequestMethod.POST) public String processSubmit( @ModelAttribute("edit") Edit edit, BindingResult result, SessionStatus status) {
  • The @RequestBody and @ResponseBody annotations @RequestBody annotated parameters for access to the HTTP request body. Parameter values are converted to the declared method argument type using HttpMessageConverters. If the method is annotated with @ResponseBody, the return type is written to the response HTTP body. The return value will be converted to the declared method argument type using HttpMessageConverters (a href='http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html'>Reference)
  • The functionality offered by the RestTemplate Similar to the WebServiceTemplate The central class for client-side HTTP access. It simplifies communication with HTTP servers, and enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible template variables) and extract results. (a href='http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/client/RestTemplate.html'>Reference)

JMS with Spring

General

  • Where can Spring-JMS applications obtain their JMS resources from The container provides the resource, which can be a standalone JMS provider (eg. ActiveMQConnectionFactory) or an application server (jee:jndi-lookup jndi-name="...") - is valid for ConnectionFactory and Destination
  • The functionality offered by Spring's JMS message listener container, including the use of a MessageListenerAdapter through the 'method' attribute in the element With the a MessageListener call be called, by specifying the method attribute, any POJO can be used (automatically a MessageListenerAdapter is generated for the POJO by the framework)
  • The functionality offered by the JmsTemplate JmsTemplate delegates to MessageConverter and DestinationResolver. MessageConverter: String -> TextMessage, Serializable -> ObjectMessage, Map -> MapMessage, byte[] -> BytesMessage DynamicDestinationResolver or JndiDestinationResolver, simple one-method-interface Also ConnectionFactory necessary to create a JmsTemplate

Transactions

Local JMS Transactions with Spring

  • How to enable local JMS transactions with Spring's message listener container acknowledge="transacted"
  • If and if so, how is a local JMS transaction made available to the JMSTemplate sessionTransacted=true ConnectionFactoryUtils.doGetTransactionalSession
  • How does Spring attempt to synchronize a local JMS transaction and a local database transaction DataSourceTransactionManager: commit only after successful database commit
  • The functionality offered by the JmsTransactionManager send and receive multiple messages in one transaction works together with declarative transaction management

JTA and Two-phased commit transactions with Spring

  • What guarantees does JTA provide that local transactions do not provide ACID guarantees: Atomic, Consistent, Isolated, Durable ...but on local transactions only in a single resource

Batch processing with Spring Batch

General

  • Main concepts (Job, Step, Job Instance, Job Execution, Step Execution, etc. Job has its own identity, has steps, has an execution (which has start and stop times and status) Client starts JobLauncher, which starts Job (use JobParameters to create JobInstance, which has JobExecutions - same for steps) JobLauncher also updates Job metadata in JobRepository Reader (single entry) and Writer (chunked) with FieldSetMapper
  • The interfaces typically used to implement a chunk-oriented Step implements ItemWriter with write(List list) method
  • How and where state can be store Is handled by JobRepository (ie. in a database or a Map)
  • What are job parameters and how are they used JobParameters can parameterize a JobInstance (eg. schedule.date)
  • What is a FieldSetMapper and what is it used for Can be used to customzie an FlatFileItemReader, which uses it to map values (with LineTokenizer and FieldSetMapper)

Spring Integration

General

  • Main concepts (Messages, Channels, Endpoint types) Message Channel, Message Endpoint, Pipes and Filters, Message Router, Message Translator Framework polls to an event source and notifies/invokes services as necessary (SoC) Rules: A Message is sent by an Endpoint, Endpoints are connected by Channels and receive Messages from them A Message is MessageHeaders and a payload - is immutable always A MessageChannel is used for decoupling, with optional buffereing MessageChannel can be Point-to-Point, Publish-subscribe and Pollable Types of MessageEndpoints (which are the filters in "pipes-and-filter"): Channel Adapter (Jms, File, Method invokation), Service Activator (Invoke Method and wrap result), Gateway (two way integration, sync, inbound waits for reply, outbound waits for response)
  • How to programmatically create new Messages Use MessageBuilder (is immutable, uses Builder pattern)
  • Using chains and bridges Chain subsumes several different Endpoints in one channel Uses same Thread, Transaction Boundaries, etc.

Synchronous vs. asynchronous message passing

  • The different Channel types and how each of them should be used Subscribable (Direct, Publish Subscribe) Pollable (Queue, Priority, Rendezvous)
  • The corresponding effects on things like transactions and security Context is lost by switching to queued channel (sync -> async)
  • The need for active polling and how to configure that Active components are sometimes necessary (JMS, File, etc.) Configure poller on the Enpoints

(Reference)

Posted in Uncategorized | 13 Comments »

Groovy vs. Ruby – the CSV shootout (7L7W day 3)

Posted by ice09 on October 18, 2011

Nope, there is no rant here. Even more, there is no CSV shootout. However, a little CSV is here, it’s even Meta-CSV somehow.

Ok, let’s clarify this: I just started reading the book “Seven Languages in Seven Weeks” and I already like it. It’s exactly written for someone on my language-knowledge level, ie. someone who tried and used several languages and is pretty good at getting the differences between OO and functional languages, but has difficulties to explain what differentiates Clojure from Scala from Haskell from Io besides the different kinds of typing (static vs. dynamic). Someone who has heard of but never knew what prototypes are about and what specialities each language defines (the movie comparison also helps a lot. But be aware that Prolog developers have to relax a little and accept to be compared to Rain Man).

So, the first day is about Ruby. I know Groovy pretty well, so I thought that would be easy. It was. But, I realize that the subtile differences matter a lot. In short, I feel that Ruby is much more consistent (you will see by the sample). However, I like Groovy more – after all, for a Java developer it’s the much better fit. But also, I like the even more magic – which I’d hate in big production systems but really love for scripting.

So, the sample is a CSV reader – the Ruby part is much longer than it has to be, but it should show the Metaprogramming mechanisms. And I like them a lot, even more than the Groovy ones (though Categories are really cool for scoping the Metaprogramming).

class CsvRow
  attr_accessor :values, :keys
  
  def initialize( keys, values )
    @keys = keys
    @values = values 
  end
  
  def method_missing(id, *args)
    if (id==:to_ary) 
      then return @values 
      else return @values[@keys.index(id.to_s)]
    end
  end
end

module ActsAsCsv
  def self.included(base)
    base.extend ClassMethods
  end
  
  module ClassMethods
    def acts_as_csv
      include InstanceMethods
      include Enumerable
    end
  end
  
  module InstanceMethods   
    attr_accessor :headers, :csv_contents
    
    def each &block
       @csv_contents.each{|csvRow| block.call(csvRow)}
    end
    
    def read
      @csv_contents = []
      filename = self.class.to_s.downcase + '.txt'
      file = File.new(filename)
      @headers = file.gets.chomp.split(';').collect{|s| s.delete("\"")}
      
      file.each do |row|
        values = row.chomp.split(';').collect{|s| s.delete("\"")}
        @csv_contents << CsvRow.new(@headers, values)
      end
    end
    
    def initialize
      read 
    end
  end
end

class RubyCsv  # no inheritance! You can mix it in
  include ActsAsCsv
  acts_as_csv
end

m = RubyCsv.new
m.each { |it| puts it.Kontonummer }

I will not explain how this works here, there are bazillions of resources of people really knowing Ruby. The most important fact is how the Metaprogramming works – and it does it exactly as expected. Even more, it does it right. The best fact to me is that upon including the module (which unfolds itself into the base class very nicely), the include method is called automatically. There is no dependency of the RubyCsv on it’s Mixin (and there shouldn’t be!).

So, this is pretty cool. How do I achieve this in Groovy? This is diffficult, there are no modules in Groovy. Of course, Metaprogramming is easy in Groovy, but I want it to mimick the Ruby script.

The most I can get is by using the Groovy 1.6 @Mixin annotation like this:

class CsvRow {
    def keys = []
    def values = []
    
    def propertyMissing(String name) { 
        values[keys.indexOf(name)]
    }
}

class ActAsCsv {
    public headers = []
    public csvRows = []
    
    def read(def instance) {
        new File("rubycsv.txt").eachLine {
            if (instance.headers.isEmpty()) {
                instance.headers = it.trim().split(';').collect{it.replaceAll("\"", "")}
            } else {
                def values = it.trim().split(';').collect{it.replaceAll("\"", "")}
                instance.csvRows << new CsvRow(keys:instance.headers, values:values)
            }
        }
    }

    def iterator() {
        csvRows.iterator()
    }
}

@Mixin(ActAsCsv)
class GroovyCsv {
    GroovyCsv() {
        read(this)
    }
    //@Delegate ActAsCsv acter = new ActAsCsv()
}


def act = new GroovyCsv()
println act.collect { it.Buchungstext.reverse() }
act.each { println it.Kontonummer }

So, this is nice as well, but compared to Ruby it’s more clumsy. The worst thing is the trick with calling the Mixin in the constructor with the this reference. It does not work otherwise, since the fields cannot be set on the Mixin-GroovyCsv-instance itself. This is weird and costs time to debug. It is not a real dependency upon the Mixin itself, but it’s just superfluous.
Also, the nice template method style of including modules in Ruby is not the same. It fells better in Ruby (look up the Enumerable inclusion, it’s really nice). On the other hand, just having to declare iterator() the right way to get rid of all Metaprogamming to implement the Collection methods correctly is cool as well. Also, I found it cleaner to use the @Delegate possibility, which works exactly as expected (no this weirdness here).

It’s as always, there is no best way, I like both versions a lot. I still feel that Ruby feels cleaner, but I can achieve everything in Groovy with the same “expressiveness”. But I can use all Java and all it’s environment and tools as well – so jep, to me it’s the better choice. But I see where a lot of the good stuff in Groovy comes from.

Posted in Groovy, Ruby | Leave a Comment »

DSLs made easy – with Groovy’s chain method calls (GEP 3)

Posted by ice09 on October 7, 2011

As you probably know, the creation of DSLs is quite easy these days. Take Groovy or Scala and the creation of internal DSLs is a day’s work. Take Xtext 2.0 and the creation of an external DSL is a two days’s work.

However, let’s assume you do not have a day, but two hours left – still possible? Yes, indeed. With Groovy 1.8 and its new chained method calls (contributed by GEP 3).

So, chained method calls have always be possible in Groovy, but the new “conventions” of GEP 3 make the creation of a DSL really straightforward, since with a little effort you can design a DSL which has no brackets and dots at all!

.use case.

A sample use case for a simple DSL is the evaluation of account data. I wanted to have

  • the possibility to parse downloaded CSV files
  • enrich the items with certain categories
  • store them in a local (file based) database
  • be able to evaluate the items for certain time spans and categories

Having thought about the GUI which I would have to create for this use case, I felt overwhelmed immediately, given that my design capabilities are … debatable. But also, I would like to be able to use the data in several ways, transform it, check and validate it and so on. For this I do not want to create my own command set, but I want to use Groovy commands for this. Namely, I want to create an internal DSL.

.sample.

The following commands I can think of. However, this is not complete

load savingsfile     scans a predefined directory for the newest CSV file with a certain pattern and reads this file into memory 
                     (as a list of string arrays)
filter database      filter the data in memory against a predefined database file and remove all items from memory which are in the 
                     database already (depends on load step)
categorize data      use a certain rule set (external configuration) to automatically categorize the items according to different properties
                     (like sender/receiver of money)
show data            show the actual data in memory
save database        store the actual data in database file (filter step must be executed first)

Moreover, the DSL should allow for evaluating the data in memory, with the following syntax

evaluation of date september, 2011 category "Clubbing" with display           evaluate the database and display evaluation for 
                                                                              september, 2011 in category "Clubbing"
evaluation of date always category "Clubbing" without display                 same as above, but for no specified time span
evaluation of date always category all with display                           same as above, but for no specified time span and no specified category
evaluation of date always category all without display                        same as above, but without display of data (yes, it might not make sense -
                                                                              but it's possible :))

Now, the thing is that I would like to be able to execute all these commands several times, for different data and – since the data is available as a list of string arrays – I know I can do whatever I want with it within Groovy.
So, if I do not have a GUI, what about a shell? Of course, Groovy has one. What about TAB completion on my shiny new DSL – sure, why not? (ok, honestly, due to type inferencing difficulties, this does not work completely, but it’s a help definitely – just try it!)

So, let’s go. Just start the Groovy shell (GROOVY_HOME/bin/groovysh) and copy & paste this code. Yes, that’s just the skeleton to show the important parts – but there is a working version here, which works if you are customer of the German Sparkasse (shouldn’t they pay me for this?). If you really want to use this “real”, working version, you will need a rule file, which must be named rules.properties and has key/value pairs of regular expressions for the sender field like PAYPAL=Paypal or ^GA=Geldautomat.

class Savings {
    def read = false
    def filtered = false
    def datenbank
    Savings(datenbank) {
        this.datenbank = datenbank
    }
    def load(sfile) {
        read = true
        println "file loaded."
        this
    }
    def display(dummy) {
        if (!read) println "no data available."
        else println "display called."
    }
    def filter(sfile) {
        filtered = true
        println "data is filtered."
        this
    }
    def categorize(cat) {
        println "categorize called with category ${cat}."
    }
    def save(sfile) {
        if (!filtered) println "data is not filtered, aborting storing."
        else println "data is stored in file $datenbank"; read = false
    }
}

class Evaluation {
    def month
    def year
    def display = false
    def category
    def date(Integer month, Integer year) {
        this.month = month
        this.year = year
        this
    }
    def date(all) {
        this.month = null
        this.year = null
        this
    }
    def without(display) {
        this.display = false
        evaluate()
    }
    def with(ausgabe) {
        this.display = true
        evaluate()
    }
    def category(category) {
        if (category.toString() != "all")
            this.category = category
        this
    }
    def evaluate() {
        println "evaluate ${(month != null) ? "month ${month+1} year $year" : "all"} in category $category ${display ? "with":"without"} display"
    }
}

enum words { savingsfile, category, of, data, database, all, always, with, without, display }
(january, february, march, april, may, june, july, august, september, october, november, december) = (0..11)
datenbank = "db.csv"
import static words.*

savings = new Savings(datenbank)

read = { file -> savings.load(file) }
showit = { speicher -> savings.display()}
filter = { file -> savings.filter(file)}
categorize = { speicher -> savings.categorize(speicher)}
store = { file -> savings.save(file)}
evaluation = { of -> new Evaluation() }

//sample commands

read savingsfile
filter database
categorize data
showit data
store database

evaluation of date september, 2011 category "Clubbing" with display
evaluation of date always category "Clubbing" without display
evaluation of date always category all with display
evaluation of date always category all without display

The last lines (from //sample commands) are actual commands of the DSL. Try these with TAB completion in the shell and see what’s possible and what’s not. I will not explain the functionality in detail, because there are several resources which can be used for clarification.

.conclusion.

I wanted to show that two hours can be enough to create your own DSL, together with the Groovy shell this is a really powerful way to let people with limited technical abilities use the power of the complete Java/Groovy platform in interactive mode! Imagine the possibilities – your business analysts will love you.

Obviously, I had to fit the DSL to the conventions of GEP 3 (and moreover, I had to rename “load”, “show” and “save”, since these are reserved keywords in the Groovy shell…), but still I think it’s worth it. But if you take care of DSL design and do not want the language to be restricted by the command chain conventions, look for a cleaner approach. For quick & dirty API usage easing, this works as a charm.

If this blog post was useful to you, you can tip me. Maybe you do not want to tip, but please inform yourself about Bitcoin and applications of Bitcoin like Youttipit.

Posted in DSL, Groovy | Leave a Comment »

Integrating Spring 3 and MyBatis 3 using the Spring JDBC namespace

Posted by ice09 on July 25, 2011

Sources to this blog post are available here. These can be used with Maven 3 and are best suitable for the SpringSource Tool Suite 2.7.1 (just import the unzipped project as “Existing Maven project”)

There are several tutorials about the integration of MyBatis 3 in Spring 3 applications, which is kind of special. Even more tutorials are available about the usage of the Spring-JDBC-namespace, mostly together with an embedded database for for unit tests.

This post will show how to combined these mechanisms using the SpringSource Tool Suite 2.7.1.
There is an explanation of the project artifacts first. Afterwards, a step-by-step guide shows the main steps for the creation of a skeleton of this sample project in the SpringSource Tool Suite.

The project structure

The unit test IntegrationTests.java

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class IntegrationTests {
	
	@Autowired
	private UserService service;

	@Test
	public void testGetFirstUser() throws Exception {
		assertNotNull(service);
		assertEquals("Customer1", service.getFirstUser());
	}
	@Test
	public void testFindUserByName() throws Exception {
		assertNotNull(service);
		assertEquals("0", service.findUserByName("Customer1"));
		assertEquals("1", service.findUserByName("Customer2"));
	}
}

The corresponding configuration file IntegrationTests-context.xml

<beans>
	<import resource="classpath:/META-INF/spring/app-context.xml"/> 

	<jdbc:embedded-database id="dataSource">
		<jdbc:script location="classpath:/de/ice09/blog/init-sql/schema.sql" />
		<jdbc:script location="classpath:/de/ice09/blog/init-sql/data.sql" />
	</jdbc:embedded-database>
</beans>

The referenced DDL-SQL for the (embedded test) database (hsqldb)

drop table customer if exists;
create table customer (id integer identity primary key, name varchar(50) not null );

The referenced SQL for initialization of the (embedded) database

insert into customer (name) values ('Customer1');
insert into customer (name) values ('Customer2');

Referenced app-context.xml – the main configuration file

<beans>
	<import resource="classpath:/META-INF/spring/dao-context.xml" />
	<context:component-scan base-package="de.ice09.blog" />
</beans>

The included dao-context.xml infrastructure and DAO configuration file

<beans>
	<!-- infrastructure -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- MyBatis Mapper -->	
	<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
		<property name="mapperInterface" value="de.ice09.blog.dao.mybatis.UserMapper" />
		<property name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean>
</beans>

The service interface

public interface UserService {
	String getFirstUser();
	String findUserByName(String name);
}

The UserService implementation with injected DAO-Mapper

@Component
public class UserServiceImpl implements UserService {
	
	@Autowired
	private UserMapper userMapper;
	
	public String getFirstUser() {
		List<User> users = userMapper.getUsers();
		return users.get(0).getLastName();	
	}
	public String findUserByName(String name) {
		return userMapper.findUserByName(name).getId();
	}
}

The mapper with two possible configuration, the getUsers annotated config and the findUsersByName configuration in XML (see below)

public interface UserMapper {
	@Select("SELECT id, name as lastname FROM customer")
	List<User> getUsers();
	
	User findUserByName(String name);
}

The sample XML configuration as an alternative for the annotation configuration (for findUserByName)

<mapper namespace="de.ice09.blog.dao.mybatis.UserMapper">
	<resultMap id="userResultMap" type="de.ice09.blog.domain.User">
	    <id property="id" column="id" />
	    <result property="lastname" column="name"/>
	</resultMap>
 
	<select id="findUserByName" parameterType="string" resultMap="userResultMap"> 
    	    select id, name from customer where name = #{value}
  	</select>
</mapper>

Creating the Project – Step by Step

Create a new Spring Template Project in STS

Choose Spring Utility Template

Add namespace to Spring XML configuration

If this blog post was useful to you, you can tip me. Maybe you do not want to tip, but please inform yourself about Bitcoin and applications of Bitcoin like Youttipit.

Posted in MyBatis, Spring | 4 Comments »

…afraid of SOAP?

Posted by ice09 on June 3, 2011

Intention

Thinking of Web Services, REST, mostly combined with JSON as the transport medium, currently is everywhere. Having done a lot for the acceptance of Web Services and furthermore simplifying the usage of Web Services themselves, there nevertheless seems to be a strong tendency to overuse REST.

How can REST be overused? This obviously depends on the use case, there are several use cases REST is not the definite answer:

  • A strictly defined format of input and output data (the data transfer format), which can easily be validated
  • A backend to backend communication, where no REST-affine language like JavaScript is used
  • Communication between legacy systems which would have to have REST adapters built and already have SOAP-compliant adapters
  • Pure service-oriented components, as well as (pre-)ESB and EAI systems

So, REST is not the answer to all Web Service problems. However, it is often proposed as this. To my experience, this is mainly caused by the fact that people think SOAP is just too complicated, not suitable for light services and just too much overhead. Even though that might be true with respect to WS-*, it is really quite easy to setup Web Services server and clients (and tests) which use SOAP – with no hassle.

The User Web Service – A practical approach to SOAP Web Services

We will follow a really practical approach, ie. many pictures, almost no theoretical background. However, whenever necessary, a link will be present to sites explaining the theoretical background.

In this post, Spring Web Services 2 is used for the server and client side. Even though there are “easier” frameworks around, which make creation of (SOAP) Web Services from existing Java code a breeze, this is exactly the approach you should not follow, if maintenance, extensibility and flexibility is of concern.

So, here is the first drawback: we will use the slightly more complicated “contract-first” approach. But just believe in me: after having dealt with several Web Services, you will never regret the challenging beginning when it comes to maintenance of existing services (including versioning, implementing fixes/patches, etc.)

Let’s go

During this post, the Spring Tool Suite (currently 2.6.0) is used. You can just as well use Eclipse (or any other IDE), the STS is used since the Maven plugin is already included, as well as Spring tooling, which supports Spring Web Services and eases usage of this framework.

  1. Download SpringSource Tool Suite
  2. Create new Maven Project with spring-ws-archetype
  3. Add XML Schema (the contract)
  4. Generate JAXB classes, the XML-Java data binding from the XML Schema files
  5. Create Endpoint and Spring WS annotations and config
  6. …that’s it – test it

Step 2: Create new Maven Project with spring-ws-archetype

Choose “File / New / Other… / Maven Project”

mvn_new

Choose “archetype selection” (do not check skip…)

mvn_new_2

Choose “Add archetype” and type values according to screenshot (we need to add at least version 2.0.2, currently only 2.0.0-M1 is available in catalog)

mvn_choose_at

Choose the added archetype from selection

mvn_new_4

Choose the settings for your project, these values are arbitrary (for testing purposes you can use the ones from the screenshot)

mvn_new_5

The steps above can be shortened by just creating the Maven project from the command line and importing the generated project as an existing maven project in STS/Eclipse (with “File / Import / Existing Maven project”).

mvn archetype:create -DarchetypeGroupId=org.springframework.ws -DarchetypeArtifactId=spring-ws-archetype -DarchetypeVersion=2.0.2.RELEASE -DgroupId=de.ice09.blog -DartifactId=userservice-ws

However, for this to work Maven has to be installed correctly, M2_HOME and JAVA_HOME have to be set correctly, etc. Using the steps above just require STS or Eclipse + Maven plugin to be installed.

More details about these steps are available in this short & nice blog post.

Right now this project structure should have been generated

structure_1

Step 3: Add XML Schema (the contract)

There are several ways for creating a XML Schema, you can use XMLSpy, which to me is the best tool for this task, but is quite expensive. The XML Schema editor in Eclipse is quite useful as well (and integrated and free).

A recent discovery is WMHelp XMLPad, which is pretty cool and supports diagrams similar to those of XMLSpy:

GetUser

StoreUser

These diagrams are quite self-explanatory, we want to have to services, the first one accepts requests of type GetUserRequest, which just have an id and returns a GetUserResponse, which consists of id, firstname, lastname, and 1..n buddies, which themselves are just ids. The second service is StoreUser, which is the “storage” equivalent if the “reading” GetUser service.

Since the contract is the most important part of the Web Service, I will list the XML Schemas as well as sample data here, you can just skip them if you are more interested in the framework usage.

Please note: all posted source code in this blog post is just for clarifying purpose, you do not need to copy & paste this code – a complete SpringSource Tool Suite/Maven-project is available on Google Code.

XML Schema (just GetUser, StoreUser is similar)

 
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://de.ice09.blog/userservice-ws/"
	targetNamespace="http://de.ice09.blog/userservice-ws/">

    <element name="GetUserRequest">
    	<complexType>
    		<sequence>
	    		<element name="id" type="string"/>
    		</sequence>
    	</complexType>
    </element>
    
    <element name="GetUserResponse">
    	<complexType>
	    	<sequence>
	    		<element name="id" type="string"/>
	    		<element name="firstname" type="string"/>
	    		<element name="lastname" type="string"/>
	    		<sequence>
	    			<element name="Buddies">
	    				<complexType>
	    					<sequence>
	    						<element name="Buddy" type="string" minOccurs="0" maxOccurs="unbounded"/>
	    					</sequence>
	    				</complexType>
	    			</element>
	    		</sequence>
	    	</sequence>
    	</complexType>
    </element>
    
</schema>

Step 4: Generate JAXB classes, the XML-Java data binding from the XML Schema files

For the next step to work we have to enrich our Maven pom.xml with a jaxb-maven-plugin. This plugin will create the JAXB-classes from the XML Schema files during a Maven build.

str_xsd

Add the following lines to the pom.xml in the project’s root folder in section “plugins” as well as the dependencies in section “dependencies”. After saving the file, a new folder “generated-sources” in the target-folder should be created (if this does not happen, choose “Project / Clean”). These are the generated classes, which have to be added to the sources.

JAXB2-Maven-Plugin

<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>

pom_add_plugin

JAXB2-Maven-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>4.8.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <scope>compile</scope>
  <version>1.2.16</version>
</dependency>

pom_add_deps

Step 5: Create Endpoint and Spring WS annotations and config

Create a folder named “java” in src/main-folder and add this folder to the source path, analog to the generated-sources folder. This step might not be necessary in future archetype versions.

Afterwards, this classes must be added to the source folder.

//[imports removed]

@Endpoint
public class GetUserEndpoint {

        @Autowired
        private UserService userService;

        @PayloadRoot(localPart = "GetUserRequest", namespace = "http://de.ice09.blog/userservice-ws/")
        @ResponsePayload
        public GetUserResponse getUser(@RequestPayload GetUserRequest request) {
                GetUserResponse response = new ObjectFactory().createGetUserResponse();
                response.setLastname(userService.getName());
                response.setFirstname("firstname");
                return response;
        }

}

A detailed explanation of the annotation can be found on the Spring Web Services site. For now, only a minimal explanation is given: The @Endpoint annotation lets Spring know that this class will be used as a Web Service endpoint. The @Autowired annotation is standard Spring and results in the service class being injected to the endpoint automatically without XML declarations. The interesting part is the @PayloadRoot annotation in combination with @RequestPayload and @ResponsePayload. There is a lot of convention-over-configuration going on here and a lot of magic inside. If used this way, Spring recognizes the generated JAXB-classes on the classpath. When a XML request with an XML element “GetUserRequest” (localPart) and namespace “http://de.ice09.blog/userservice-ws” arrives, the generated JAXB-classes are used to marshall the XML element to a Java object due to the @Request/ResponsePayload annotations and the presence of JAXB and the generated JAXB-classes on the classpath.

If this is new to you, you should get familiar with it, otherwise it will fall back on you if you have to change anything, eg. from JAXB to Castor, DOM, XPath or whatever. This described usage (JAXB and annotations) is the easiest way possible, but the framework allows for almost any thinkable combination and framework usage. There might be more configuration necessary though.

The service is just listed for completeness, it does nothing special. Just note the @Coomponent annotation. This lets Spring know that this bean/class will be injected somewhere, eg. by using @Autowired as we did.

de.ice09.blog.ws.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {

        public String getName() {
                return "lastname";
        }

}

Now for the most interesting component, the Spring config. It is already present in the WEB-INF directory. You just have to insert these XML elements:

<?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:sws="http://www.springframework.org/schema/web-services"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

        <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
                <property name="soapVersion">
                        <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
                </property>
        </bean>

        <sws:annotation-driven />

        <context:component-scan base-package="de.ice09.blog.ws" />

        <sws:dynamic-wsdl id="GetUser" portTypeName="UserManagement"
                createSoap12Binding="true" createSoap11Binding="false" locationUri="/userservice"
                targetNamespace="http://de.ice09.blog/userservice-ws/">
                <sws:xsd location="/WEB-INF/GetUser.xsd" />
        </sws:dynamic-wsdl>

        <sws:dynamic-wsdl id="StoreUser" portTypeName="UserManagement"
                createSoap12Binding="true" createSoap11Binding="false" locationUri="/userservice"
                targetNamespace="http://de.ice09.blog/userservice-ws/">
                <sws:xsd location="/WEB-INF/StoreUser.xsd" />
        </sws:dynamic-wsdl>

</beans>

The most important element is <sws:annotation-driven>, together with <context:componant-scan>. These elements do all the magic, I highly advise you to get accustomed to the way these elements work. The other parts are just for automatic WSDL generation, which eases the usage of the generated Web Services a lot, but are not necessary for the services themselves. The messageFactory is just for compliance with SOAP 1.2 and can be ignored – just make sure you include it if you want to use SOAP 1.2 instead of SOAP 1.1. Same is true for the dynamic WSDL-generation – the attributes must be set to true and false respectively.

For the WSDL generation, the web.xml has to be modified as well, just add the init-param lines:

<servlet>
        <servlet-name>spring-ws</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>

Step 6: …that’s it – test it

Yes, that’s it. We created a complete new Web Service with really simple steps.

Just start the Web application now on the STS included tc-Server, just by right-clicking the project and choosing “Run As… / Run on Server”

run_final

Afterwards, navigate to http://localhost:8080/userservicews/GetUser.wsdl there should be a WSDL printed in the browser.

We can now test the Web Service with a Web Service client, for now we will use soapUI, which is a pretty neat tool for this purpose. You can Web Start it or download it, it requires no install. Even better than soapUI is the Spring Web Service client, which we will investigate in the following blog entry.

After starting soapUI, create a new project and provide the aforementioned WSDL-Url. soapUI will ask for creating a test suite and test cases, which should just be unmodified accepted.

soapui_new

soapui_new_1

If everything worked, you can just choose the created test suite with its test case and run the test case. The result should look like the screenshot.

soapui_run

If this blog post was useful to you, you can tip me. Maybe you do not want to tip, but please inform yourself about Bitcoin and applications of Bitcoin like Youttipit.

Posted in SOAP, Spring Web Services | 4 Comments »

Mocking and Stubbing with Mockito

Posted by ice09 on January 9, 2011

 

Intention

Let’s assume there is a new requirement for an existing CRM-like system: send a mail to all customers with a balance greater than 1000. Since we are not allowed to access the database directly, we will have to use existing services.

image

Since we are using Spring, the configuration is obvious, the services are injected, that’s it.

Mocking

However, for testing purposes, we want to mock the services. By examining the classes and methods, we will see why mocking is necessary, but not enough in this case.

Setup

Only the interfaces of the services are shown, they are mocked anyway.

MailService

 
public interface MailService { 
    
    void sendMails(List<customer> customers); 

}

CustomerDao

 
public interface CustomerDao { 

    List<customer> getCustomers(); 

} 

This is the class under test, the filter method should be tested.

 
public class CustomerService { 
    
    private CustomerDao customerDao; 
    private MailService mailService; 
    
    public void notifyCustomersWithBalanceGreaterThan(long cbalance) { 
        List<customer> notificationList = new ArrayList<customer>(); 
        List<customer> customers = customerDao.getCustomers(); 
        for (Customer customer : customers) { 
            if (customer.getBalance() > cbalance) { 
                notificationList.add(customer); 
            } 
        }
        mailService.sendMails(notificationList); 
    } 

} 

Testing…

How do we test if everything worked? There is no result object to check, since mails are sent. Here mocking comes into play, a breeze with Mockito.

 
@RunWith(MockitoJUnitRunner.class)
public class TestClass {

	private @Mock CustomerDao customerDao;
	private @Mock MailService mailService;
	
	private @InjectMocks CustomerService customerService = new CustomerService();

	private @Captor ArgumentCaptor<List<Customer>> customerCaptor;

	@Before
	public void setup() {
		MockitoAnnotations.initMocks(this);
	}

	@Test
	public void testIt() {
		//preparation (stubbing)
		when(customerDao.getCustomers()).thenReturn(prepareList());
		
		customerService.notifyCustomersWithBalanceGreaterThan(1000);

		//verification (mocking)
		//has customerDao be called correctly?
		verify(customerDao, times(1)).getCustomers();
		verifyNoMoreInteractions(customerDao);

		//have the mails be sent?
		verify(mailService).sendMails(customerCaptor.capture());
		
		//is the list of customers to notify correct? 
		assertEquals(2, customerCaptor.getValue().size());
		assertEquals(new Customer(3, "eva", "mustermann", 2000), customerCaptor.getValue().get(0)); 
		assertEquals(new Customer(6, "hanna", "mustermann", 1001), customerCaptor.getValue().get(1)); 
		verifyNoMoreInteractions(mailService);
	}

	private List<Customer> prepareList() {
		List<Customer> customers = new ArrayList<Customer>();
		customers.add(new Customer(1, "hans", "mustermann", 100));
		customers.add(new Customer(2, "max", "mustermann", 1000));
		customers.add(new Customer(3, "eva", "mustermann", 2000));
		customers.add(new Customer(4, "anna", "mustermann", 0));
		customers.add(new Customer(6, "hanna", "mustermann", 1001));
		return customers;
	}

}

The mocking part is straightforward. However, we have to stub as well, since we want the CustomerDao to actually return our prepared Customer list. No problem with Mockito (search for Test Spy to see why there are differences in Mocking frameworks regarding the support of Mocking, Stubbing or both – then being a Test Spy).

Dependency injection

Really interesting is the wiring of the components. The MockitoJUnitRunner.class is used to run the Unittest, we do not use Spring for this test. But magically, after calling MockitoAnnotations.initMocks(this) the @Mock annotated Mocks are injected into the @InjectMocks annotated class automatically. This being great already, we are furthermore using the @Captor annotation to create a argument captor for all List arguments. Now we can examine the submitted list with Customers to sent mail to and determine, if the correct Customers have been filtered.
So, we have a nice dependency injection, combined with stubbing and mocking. Mockito is really powerful (and much easier to use than similar Mocking frameworks), you can even partially stub objects. However, there should be a really good reason for doing this…

Posted in Uncategorized | 1 Comment »

QuickTip: SCP with Groovy, Maven and Eclipse

Posted by ice09 on December 20, 2010

Intention

It’s easy to use SCP with Java, Groovy and even with Maven. However, it gets more complicated if you want to use all of them simultaneously.

It should work this way: An (key-file-based) SCP-connection should take place in a Groovy, so the transferred file can be manipulated straight away. All this should be triggered by a Maven build process and alternatively, using Eclipse with the Groovy plugin, it should be possible to directly start the Groovy script.

Preparation

Either Eclipse with the Groovy plugin and the Maven plugin or the SpringSource Tool Suite (which includes both plugins) should be installed.

Maven config

The Maven config consists of two dependencies:

  1. The Ant-SCP-Plugin, which is based on JSch
  2. Embedded Groovy (groovy-all.jar)

And two Maven Plugins:

  1. GMaven
  2. The Exec Maven Plugin

<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>de.ice09.scp</groupId>
 <artifactId>jsch</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <dependencies>
  <dependency>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jsch</artifactId>
   <version>1.8.1</version>
  </dependency>
  <dependency>
   <groupId>org.codehaus.groovy</groupId>
   <artifactId>groovy-all</artifactId>
   <version>1.7.5</version>
  </dependency>
 </dependencies>
 <build>
  <plugins>
   <plugin>
    <groupId>org.codehaus.groovy.maven</groupId>
    <artifactId>gmaven-plugin</artifactId>
    <executions>
     <execution>
      <goals>
       <goal>generateStubs</goal>
       <goal>compile</goal>
       <goal>generateTestStubs</goal>
       <goal>testCompile</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.1</version>
    <executions>
     <execution>
      <goals>
       <goal>java</goal>
      </goals>
     </execution>
    </executions>
    <configuration>
     <mainClass>de.ice09.scp.LogLoader</mainClass>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>

Groovy…

Here comes the Groovy part, in fact it’s quite short, since it focuses on the file transfer part. Obviously, it would be easy to manipulate the transferred files after the SCP-transfer, since we are inside a Groovy script and we can use whatever Java library we want since we are inside a Maven project. The universe is ours!


package de.ice09.scp

new AntBuilder()
 .scp(
  file:"root@server.com:/tmp/ls",
  todir:'C:/temp',
  verbose:true,
  trust:true,
  keyfile:'C:/portables/PuTTY/ossh.ppk',
  passphrase:'passphrase'
 )

The file must go to src/main/groovy for GMaven to work. The key must be OpenSSH-compliant. If you use PuTTY, you can export this format. Alternatively, you can use username/password instead.

Testing…

After creating a new Maven project with the pom.xml listed above, more than half of the work is done. With or without an IDE this can be tested. Just run

maven clean install exec:java

GMaven should generate the Java stubs, the Execution Plugin should execute the generated Java class file. The dependencies for JSch, Antbuilder etc. are handled by Maven or Groovy itself.

Eclipse config

The final step is to enable the Groovy nature in Eclipse. This leads us to a faster development cycle, since the Groovy script can be run “natively”, without having Maven to generate the Java stub before. There is no problem running the two options (Groovy with Maven and Eclipse) side-by-side, so it is really easy to develop and deploy, since there is no big difference. You always have a completely runnable version available, given that Maven is installed on the target system.

Convert to Groovy project

2010-12-20_23-16_Java

Add Groovy sources (from src/main/groovy) to classpath

2010-12-20_23-19_Java

The deployable way: start process using GMaven and Execution Plugin

2010-12-20_23-36_Run Configurations

Start in development mode using the Groovy Eclipse Plugin

2010-12-20_23-38_Java

Posted in Groovy, Maven | 1 Comment »

Preparing a fresh Debian Lenny for Java Enterprise Applications

Posted by ice09 on December 18, 2010

Intention

I am a happy owner of a virtual root server – this being a great thing, there is one big problem: I have to prepare this box for Java usage myself. This must be achieved with a somewhat limited Linux knowledge. However, with debian lenny this turned out to be a breeze.

I had to follow the steps below to get this running in about 30 minutes:

  1. Apache Webserver
  2. MySQL
  3. phpMyAdmin
  4. GlassFish 3

Which is pretty much what you need for creating JEE/Spring-Applications in an enterprise scale.

What is still missing (due to a lack of time and necessity) are the following configurations:

  1. JNDI-Resource for the MySQL-Database
  2. Apache/GlassFish-mod for forwarding requests on port 80 to GlassFish directly

List of Commands

cat /etc/debian_version

For my installation this says 5.0.7. So obviously: 1. I am using Debian. 2. It is Debian Lenny in version 5.0.7. Yes, we are starting slowly here.

apt-get install apache2

Install the Apache Web Server. I more or less need it for phpMyAdmin. Obviously, you can choose lighthttpd or others here.

apt-get install mysql-server mysql-client phpmyadmin

This is the most important line, it magically does everything exactly like you want to have it (however, this depends on answering the questions during installation correctly).

apt-get install sun-java6-jdk

Ok, this is important as well for Java development. I did not expect it to be that easy (remembering licensing issues in the past) and tried it “manually”, but was lost almost immediately. However, with sun-java6-jdk, you will get everything you need. You should check this with:

java –version

which should print out text like this:

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03, mixed mode)

Your mileage may vary here of course. It should show 1.6 somewhere though.

Now, the most “difficult” part is the installation of GlassFish. Not surprisingly, we are not the first trying to install GlassFish on Debian, so there exists a really good documentation about this topic here (in German): http://www.bennyn.de/webanwendungen/virtual-server/glassfish-v3-installieren-auf-debian-lenny.html

Since this HOWTO here should be complete, I am reposting the steps here:

wget -O /opt/glassfish-3.0.1.zip http://download.java.net/glassfish/3.0.1/release/glassfish-3.0.1.zip
cd /opt/
unzip glassfish-3.0.1.zip
rm glassfish-3.0.1.zip
cd /etc/init.d/

Now, only the script glassfish.sh is missing:

vim /etc/init.d/glassfish.sh
touch glassfish.sh
chmod 0755 glassfish.sh    
update-rc.d glassfish.sh defaults

with this content (all taken from the site mentioned above):

#!/bin/sh
### BEGIN INIT INFO
# Provides:          glassfish
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO
#
# This init.d script is used to start the glassfish application server.
# Simplest possible case -- no password file, one default domain
#
 
GLASSFISH_HOME=${GLASSFISH_HOME:-"/opt/glassfishv3/glassfish"}
 
case "$1" in
start)
	$GLASSFISH_HOME/bin/asadmin start-domain | tee -a /var/log/glassfish.log
	;;
stop)
	$GLASSFISH_HOME/bin/asadmin stop-domain | tee -a /var/log/glassfish.log
	;;
restart)
	$GLASSFISH_HOME/bin/asadmin restart-domain | tee -a /var/log/glassfish.log
	;;
*)
    echo "usage: $0 (start|stop|restart|help)"
esac

Posted in Debian, GlassFish | 2 Comments »

Spring-batch with GMail-Notification using Velocity

Posted by ice09 on August 15, 2010

The sources to this blog entry are available here. The SpringSource Tool Suite (STS) or an accordingly configured Eclipse (with a mandatory Maven plugin and an optional Spring IDE plugin) has to be installed.

The problem

The Spring Batch project is really useful in creating new batch jobs. The framework is straightforward and gained quite a lot usefulness and user-friendliness with the 2.x branch. However, even with the great reference documentation and the getting started section, it takes its time to create a simple project with success/error-mail notification.
I will create a really simple batch job using the new 2.x features, adding the almost always necessary mail notification after a successful or failed job execution. The mail context should be rendered using Velocity. This post does not explain the Spring (Batch) components used, please refer to the Spring Batch reference documentation for detailed explanations.

The setup

The structure is taken from the Template Project in STS, the howto is available in the getting started page.

project structure

It is important to note the separation of concerns in the two spring contexts launch-context.xml and module-context.xml. The first one contains all beans relevant to the job’s infrastructure, there is no business logic contained. The module config is included using import resource. The module config just contains business logic, the actual batch job logic is configured here.

module-config.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:batch="http://www.springframework.org/schema/batch"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd">

	<batch:job id="job1" xmlns="http://www.springframework.org/schema/batch">
		<batch:step id="step1" parent="simpleStep">
			<batch:tasklet ref="processorTasklet">
				<batch:listeners>
					<batch:listener ref="errorlistener"/>
				</batch:listeners>
			</batch:tasklet>
		</batch:step>
		<batch:listeners>
			<batch:listener ref="samplemailnotification"/>
		</batch:listeners>
	</batch:job>
	
	<bean id="samplemailnotification" parent="mailnotification">
		<property name="errorMailPath" value="mailtemplate.vm"/>
		<property name="successMailPath" value="mailtemplate.vm"/>
		<property name="subject" value="Mail from batch-sample"/>
	</bean>
	
	<bean id="processorTasklet" class="org.springframework.sample.batch.example.ExampleProcessor"/>

</beans>

The processor used just writes a data item to a shared Map. This Map is initialized and written into the job execution context by the StatusMailJobListener in its JobExecutionListener.beforeJob(...) method. In afterJob(...) this Map is evaluated and the following logic is applied: if an error-element is present, remove all provided data and just set the error-element in the Velocity context. Otherwise, copy all data from the values-element into the Velocity context. The origin of the values-element is explained below.

package org.springframework.sample.batch.example;

//[imports excluded]
public class StatusMailJobListener implements JobExecutionListener {
	
	private String recipient;
	private String sender;
	private String successMailPath;
	private String errorMailPath;
	private String subject;
	
	@Autowired
	private JavaMailSenderImpl mailSender;
	@Autowired
	private VelocityEngine velocityEngine;

	public void afterJob(JobExecution jobExecution) {
		String exitCode = jobExecution.getExitStatus().getExitCode();
		if (exitCode.equals(ExitStatus.COMPLETED.getExitCode())) {
			sendMail(successMailPath, "[OK] " + subject, jobExecution.getExecutionContext());
		} else {
			sendMail(errorMailPath, "[ERROR] " + subject, jobExecution.getExecutionContext());
		}
	}

	private void sendMail(final String messagePath, final String subject, final ExecutionContext executionContext) {
		MimeMessagePreparator preparator = new MimeMessagePreparator() {
			public void prepare(MimeMessage mimeMessage) throws Exception {
				MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
				message.setSubject(subject);
				message.setTo(recipient);
				message.setFrom(sender);
				Map<String, String> values = (Map<String, String>) executionContext.get("values");
				if (executionContext.containsKey("error")) {
					values.clear();
					values.put("error", executionContext.getString("error"));
				}
				String text = 
					VelocityEngineUtils.
						mergeTemplateIntoString(velocityEngine, messagePath, values);
				message.setText(text, true);
			}
		};
		mailSender.send(preparator);
	}

	public void beforeJob(JobExecution jobExecution) {
		Map<String, String> values = new HashMap<String, String>();
		jobExecution.getExecutionContext().put("values", values);
	}

        //[setters excluded]

}

For this setup to work, a contract is defined: every step/tasklet, which wants to add information to the context which should be available in the Velocity context for rendering the mail content, must write to the predefined Map.
This can be done eg. by using ((Map)chunkContext.getStepContext().getJobExecutionContext().get("values")).put("content", "add this text"). Initially, this Map is created by the MailNotificationListener as described above (of course, you should check for existance of this Map first in real code).
The errorhandling is done magically by Spring, if an error occurs, the Listeners can just check the ExitStatus and react accordingly (compare the afterJob(...) method).

package org.springframework.sample.batch.example;

//[imports excluded]

public class ExampleProcessor implements Tasklet {

	public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
		//throw new RuntimeException("bla");
		((Map<String, String>)chunkContext.getStepContext().getJobExecutionContext().get("values")).put("test", "[successfully invoked exampleprocessor]");
		return RepeatStatus.FINISHED;
	}

}

How and when is the error-element set into the job execution context? This is done by the last missing item, the ErrorListener, which is a StepExecutionListener.

package org.springframework.sample.batch.example;

//[imports excluded]

public class ErrorListener implements StepExecutionListener {

	public ExitStatus afterStep(StepExecution stepExecution) {
		String exitCode = stepExecution.getExitStatus().getExitCode();
		if (exitCode.equals(ExitStatus.FAILED.getExitCode())) {
			StringBuilder messages = new StringBuilder();
			for (Throwable error : stepExecution.getFailureExceptions()) {
				messages.append(error.getMessage());
			}
			stepExecution.getJobExecution().getExecutionContext().put("error", messages.toString());
			return stepExecution.getExitStatus();
		}
		return ExitStatus.COMPLETED;
	}

	public void beforeStep(StepExecution stepExecution) {
		// Nothing to do here.
	}

}

Tips & Tricks

There is not much missing, however, for this thing to run with GMail, certain properties have to be provided, therefore I will list the complete launch-config here. However, this is available in the sources to this post as well. Just fill in the correct data (GMail-account, recipients) and it should work as excepted. The velocity template is so short, I attached it as well FWIW.

launch-config.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:batch="http://www.springframework.org/schema/batch"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
		http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.0.xsd">

	<import resource="classpath:/META-INF/spring/module-context.xml" />

	<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    	<property name="transactionManager" ref="transactionManager"/>
	</bean>

	<bean id="jobLauncher"
		class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
		<property name="jobRepository" ref="jobRepository" />
	</bean>

	<bean id="transactionManager"
		class="org.springframework.batch.support.transaction.ResourcelessTransactionManager">
	</bean>

	<bean id="mailnotification" class="org.springframework.sample.batch.example.StatusMailJobListener" abstract="true">
		<property name="recipient" value="MAILADDRESS_OF_RECIPIENTS"/>
		<property name="sender" value="MAILADDRESS_OF_SENDER"/>
	</bean>
	
	<bean id="errorlistener" class="org.springframework.sample.batch.example.ErrorListener"/>

	<util:properties id="props">
		<prop key="mail.smtp.starttls.enable">true</prop>
	</util:properties>

   <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
      <property name="host" value="smtp.googlemail.com"/>
      <property name="username" value="YOUR_GMAIL_ACCOUNT"/>
      <property name="password" value="YOUR_GMAIL_PASSWORD"/>
      <property name="javaMailProperties" ref="props"/>
   </bean>

	<bean id="simpleStep"
		class="org.springframework.batch.core.step.item.SimpleStepFactoryBean"
		abstract="true">
		<property name="transactionManager" ref="transactionManager" />
		<property name="jobRepository" ref="jobRepository" />
		<property name="startLimit" value="100" />
		<property name="commitInterval" value="1" />
	</bean>
	
	<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
      <property name="velocityProperties">
         <value>
          resource.loader=class
          class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
         </value>
      </property>
   </bean>

</beans>

mailtemplate.vm

#if ($error)
Sorry, there was an error, please check the logs.<br/>
exceptionmessages: $error 
#else
Cool, it worked, there is a message for you: $test
#end

Posted in Mail, Spring Batch, Velocity | 1 Comment »