Man, it's been a while since I found a tool that just does the job no questions asked and Hazelcast definitely is one of them!
And live is good again :)
package org.example;
public class Main {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
To compile and run this one we need to invoke the javac
compiler, package it to some jar file (say example.jar
), create a manifest file (or not..) and start the application passing on the proper classpath and class name that is the entry point to our application. This might look something like this:java -cp . org.example.Main
pom.xml
reaching out beyond the magic 100k boundary...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.1.1</version>
<configuration>
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<configurationDirectory>etc</configurationDirectory>
<repositoryName>lib</repositoryName>
<repositoryLayout>flat</repositoryLayout>
<programs>
<program>
<mainClass>org.example.Main</mainClass>
<name>example</name>
</program>
</programs>
</configuration>
</plugin>
That's pretty much it! All you have to do now is to call maven to do your bidding.mvn clean package appassembler:assemble
Please note I didn't change anything in the application itself. Well that's because it's not a post about how to instantiate Spring in a console application but rather how to package everything so that it works as expected. You can take a look at a fully working example on GitHub.
<!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>
<servlet>
<servlet-name>dwr</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
As you can see here this is pretty much the basic that you'd expect from a web application that has one servlet in it. The other stuff will be done using a HTML page and a stateless local bean so let's get on with it.
Service
interface and ServiceBean
implementationpackage com.aplaline.example.ejb;
import javax.ejb.Local;
@Local
public interface Service {
String action();
}
Nothing fancy here - let's move on to the implementation:
package com.aplaline.example.ejb.impl;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.aplaline.example.ejb.Service;
@Stateless(mappedName="ServiceBean")
public class ServiceBean implements Service {
@Override
public String action() {
return "Hello, world! from EJB!";
}
}
Again... absolutely nothing fancy here - standard Hello, world! style bean. Let's see how we can configure DWR to serve the Service.action()
method...
dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
"http://directwebremoting.org/dwr/dwr30.dtd">
<dwr>
<init>
<creator id="ejb3" class="com.aplaline.dwr.Ejb3Creator" />
</init>
<allow>
<create creator="ejb3" javascript="ServiceBean">
<param name="bean" value="ear/ServiceBean/local" />
<param name="interface" value="com.aplaline.example.ejb.Service"/>
</create>
</allow>
</dwr>
Now that's the meat I'm talking about! Let's get a closer look at what's in there:
creator
package com.aplaline.dwr;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.directwebremoting.create.AbstractCreator;
import org.directwebremoting.extend.Creator;
import org.directwebremoting.util.LocalUtil;
import org.directwebremoting.util.Messages;
public class Ejb3Creator extends AbstractCreator implements Creator {
private String bean = "";
private String interfaceClass = "";
public void setBean(String bean) {
this.bean = bean;
}
public void setInterface(String interfaceClass) {
this.interfaceClass = interfaceClass;
}
@Override
public Class getType() {
try {
return LocalUtil.classForName(interfaceClass);
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(
Messages.getString("Creator.BeanClassNotFound", interfaceClass)
);
}
}
public Object getInstance() throws InstantiationException {
Context jndi = null;
try {
Properties props = new Properties();
props.load(getClass().getResourceAsStream("/jndi.properties"));
jndi = new InitialContext(props);
return jndi.lookup(bean);
} catch (Exception ex) {
throw new InstantiationException(bean + " not bound:" + ex.getMessage());
} finally {
if (jndi != null) {
try {
jndi.close();
} catch (NamingException ex) {
// Ignore
}
}
}
}
}
What it does is it allows you to specify the interface class as well as full bean name as depicted in the dwr.xml
example above.
create
index.html
<html>
<head>
<title>Example</title>
<script type="text/javascript" src="/dwr/dwr/interface/ServiceBean.js"></script>
<script type="text/javascript" src="/dwr/dwr/engine.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
ServiceBean.action(function(response) {
$("#output").append("<p>" + response + "</p>");
});
});
</script>
</head>
<body>
<h1>Example</h1>
<div id="output"></div>
</body>
</html>
This needs a word or two of explanation. At first we're including a JavaScript proxy class that will serve as a mediator between JavaScript and the server side. Then there's the required engine.js inclusion. This includes all the bits and pieces of client side DWR. Then we're including jQuery from Google CDN because I hate to re-get the library over and over again. Then there's the most interesting part - the usage: The ServiceBean
object is created by inclusion of the ServiceBean.js
resource. It automatically has a action method that takes all the parameters as the server-side counterpart would (none in this example) and as the last parameter there's a callback to execute after the response is returned. Pretty simple, right?