Code I/O

A topnotch WordPress.com site


Leave a comment

5 Minutes on Java : Validating XML data against a Schema …

Taking the idea of XML Schema generation : click here to read my previous article.  The XML document can be validated against its schema before processing it.  This is critical, otherwise, the document will be processed without validation which will be a bad process.

To illustrate XML validation, I’m using Apache XML Beans as suggested in my previous blog entry.

Here is the XMLValidator code that will help in validating XML document against a schema.

import java.io.File;
import java.io.IOException;

import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;

public class XMLValidator {
	public boolean validate(File dataFile, File schemaFile) {
		boolean status = false;

		try {
			// Only one schema to validate it against
			XmlObject[] schemas = { XmlObject.Factory.parse(schemaFile,
					new XmlOptions().setLoadLineNumbers()
							.setLoadMessageDigest()) };

			SchemaTypeLoader loader = XmlBeans.compileXsd(schemas, null,
					new XmlOptions().setErrorListener(null)
							.setCompileDownloadUrls().setCompileNoPvrRule());

			XmlObject object = loader
					.parse(dataFile,
							null,
							new XmlOptions()
									.setLoadLineNumbers(XmlOptions.LOAD_LINE_NUMBERS_END_ELEMENT));

			status = object.validate();

			System.out.println("Validation Status: " + status);
		} catch (XmlException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		return status;
	}
}


Leave a comment

5 Minutes on Java : A Java API for obtaining OAUTH tokens with an embedded callback handler

If your Java applications require OAUTH callback, then  implementing it requires a Web/App container to host it.   However, for desktop application, it will be ideal to invoke an API which will implicitly launth an embedded HTTP server, process the tokens, and return it to the caller.   User of the API can consume the tokens without worrying about the callback handler.

Java-Scribe is required by this TokenGenerator.  Here is a brief usage:

public static void main(String[] args){
		final String APP_NAME = "tg";

		// Obtain AccessKey
		if(args.length >= 3){
			String providerName = args[0].trim();
			String key = args[1].trim();
			String secret = args[2].trim();

			String scope = null;

			if(args.length == 4) {
				scope = args[3].trim();
			}
			int timeout = 1000 * 12;

			if(args.length == 5){
				timeout = Integer.parseInt(args[4].trim());
			}

			System.out.println("app = " + providerName + "n" +
					"key = " + key + "n" +
					"secret = " + secret + "n" +
					"timeout = " + timeout);

			OAuthConnection connection = new OAuthConnection();
			connection.setApiKey(key);
			connection.setApiSecret(secret);
			connection.setApiProvider(providerName);
			connection.scopeCSV(scope);

			Provider provider = ProviderFactory.getEntryByProviderName(providerName.toLowerCase());

			if(provider == null) return;

			TokenGenerator tokenGenerator = new TokenGenerator(provider, connection, timeout);
			tokenGenerator.generateToken();

			Token accessToken = tokenGenerator.getAccessToken();
			if(accessToken != null){
				System.out.println("Access Token: " + accessToken.getToken());
				System.out.println("Access Secret: " + accessToken.getSecret());
			}
		}
		// Show Usage
		else {
			StringBuffer buffer = new StringBuffer();
			buffer.append("Incorrect usage of this application!!!n");
			buffer.append("USAGE: " + APP_NAME + " <provider> <key> <secret> [scope] [timeout]n");
			buffer.append("EXAMPLE: " + APP_NAME + " twitter YOUR_TWITTER_API_KEY YOUR_TWITTER_API_SECRETn");
			buffer.append("t " + APP_NAME + " facebook YOUR_FACEBOOK_API_KEY YOUR_FACEBOOK_API_SECRET read_stream,user_status,friends_status,offline_accessn");

			buffer.append("n");

			buffer.append("Supported applicationsn");
			for(String key : ProviderFactory.getProviderNames()){
				buffer.append("* " + key + "n");
			}

			System.out.println(buffer.toString());
			System.exit(1);
		}
	}

OAuthConnection is a POJO for fundamental attributes required for an authorization.

import java.util.ArrayList;
import java.util.List;

public class OAuthConnection extends Connection {
	private String apiProvider = null;
	private String apiKey = null;
	private String apiSecret = null;
	private List<String> apiScopeList = null;
	private String accessToken = null;
	private String accessSecret = null;

	public OAuthConnection(){
		this.authentication = Authentication.OAUTH;
	}

	public String scopeCSV() {
		if(apiScopeList != null && apiScopeList.size() > 0){
			String scope = apiScopeList.toString();

			scope = scope.replace("[", "");
			scope = scope.replace("]", "");
			scope = scope.replaceAll(" ", "");

			return scope;
		}

		return null;
	}

	public String toString(){
		String scope = scopeCSV();

		return connectionName + "t" + apiProvider + "t" + apiKey + "t" + apiSecret + "t" + ((scope != null) ? scope : "null")  + "t" + accessToken + "t" + accessSecret;
	}

	public void scopeCSV(String csvText) {
		if((csvText == null) || ((csvText != null) && (csvText.length() <= 0))){
			apiScopeList = null;
		}
		else {

			String[] values = csvText.split(",");
			apiScopeList = new ArrayList<String>();

			for(String value : values){
				apiScopeList.add(value);
			}

			System.out.println(connectionName + " SCOPE: " + apiScopeList.toArray().toString());
		}
	}

	public String getConnectionName() {
		return connectionName;
	}

	public void setConnectionName(String connectionName) {
		this.connectionName = connectionName;
	}

	public String getApiProvider() {
		return apiProvider;
	}

	public void setApiProvider(String apiProvider) {
		this.apiProvider = apiProvider;
	}

	public String getApiKey() {
		return apiKey;
	}

	public void setApiKey(String apiKey) {
		this.apiKey = apiKey;
	}

	public String getApiSecret() {
		return apiSecret;
	}

	public void setApiSecret(String apiSecret) {
		this.apiSecret = apiSecret;
	}

	public List<String> getApiScope() {
		return apiScopeList;
	}

	public void setApiScope(List<String> apiScope) {
		this.apiScopeList = apiScope;
	}

	public String getAccessToken() {
		return accessToken;
	}

	public void setAccessToken(String accessToken) {
		this.accessToken = accessToken;
	}

	public String getAccessSecret() {
		return accessSecret;
	}

	public void setAccessSecret(String accessSecret) {
		this.accessSecret = accessSecret;
	}
}

ProviderFactory is a registry for Providers, this is required to pre-package third-party provider information on which the user inputs can be validated.

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class ProviderFactory {
	private static Map<String, Provider> entries = new TreeMap<String, Provider>();

	static {
		Provider provider = null;

		provider = new FacebookProvider();
		entries.put(provider.getApiProvider(), provider);

		provider = new GoogleProvider();
		entries.put(provider.getApiProvider(), provider);

		provider = new LinkedInProvider();
		entries.put(provider.getApiProvider(), provider);

		provider = new TwitterProvider();
		entries.put(provider.getApiProvider(), provider);

		provider = new FoursquareProvider();
		entries.put(provider.getApiProvider(), provider);

		System.out.println(entries);
	}

	public static Provider getEntryByProviderName(String key){
		return entries.get(key);
	}

	public static List<String> getProviderNames() {
		List<String> providers = new ArrayList<String>();

		for(String key : entries.keySet()){
			// if(key != null && key.trim().length() > 0){
				providers.add(key);
			// }
		}

		return providers;
	}
}

Here is a typical Provider interface, which must be implemented by each provider

import org.scribe.builder.api.Api;

// TODO: Refer to https://apigee.com/console/ for exploring API
public interface Provider {
	String getApiProvider();
	String getApiReference();
	ApiVersion getApiVersion();
	Class<? extends Api> getApiClass();
	List<String> getApiScopeList();
	List<RESTRequest> getApiRequestList();
}

Here is an AbstractProvider which can be extended.

import java.util.List;
import org.scribe.builder.api.Api;

public abstract class AbstractProvider implements Provider {
	protected ApiVersion apiVersion = ApiVersion.V1;

	protected String apiProvider = null;
	protected String apiReference = null;
	protected Class<? extends Api> apiClass = null;
	protected List<String> apiScopeList = null;
	protected List<RESTRequest> apiRequestList = null;

	public ApiVersion getApiVersion(){
		return apiVersion;
	}

	public String getApiProvider() {
		return apiProvider;
	}
	public void setApiProvider(String apiProvider) {
		this.apiProvider = apiProvider;
	}
	public String getApiReference() {
		return apiReference;
	}
	public void setApiReference(String apiReference) {
		this.apiReference = apiReference;
	}
	public Class<? extends Api> getApiClass() {
		return apiClass;
	}
	public void setApiClass(Class<? extends Api> apiClass) {
		this.apiClass = apiClass;
	}
	public List<String> getApiScopeList() {
		return apiScopeList;
	}
	public void setApiScopeList(List<String> apiScopeList) {
		this.apiScopeList = apiScopeList;
	}
	public List<RESTRequest> getApiRequestList() {
		return apiRequestList;
	}
	public void setApiRequestList(List<RESTRequest> apiRequestList) {
		this.apiRequestList = apiRequestList;
	}

	public AbstractProvider(){
		super();

		init();
	}

	protected abstract void init();
}

Here is an example implementation of GoogleProvider

import java.util.ArrayList;
import java.util.List;

public class GoogleProvider extends AbstractProvider {
	final static String ME = "me";
	final static String ORGANIZATION = "Informatica";
	final static String PUBLIC = "public";

	@Override
	protected void init() {
		// REFERENCE: http://code.google.com/apis/gdata/faq.html#AuthScopes
		String[] scopeArray = {
			"https://www.googleapis.com/auth/plus.me"
		};

		List<String> scopeList = new ArrayList<String>();
		for(String scope : scopeArray){
			scopeList.add(scope);
		}

		// REFERENCE: depends on what scope you need
		final String ACTIVITY_ID = "<activityId>";
		final String COMMENT_ID = "<commentId>";
		RESTRequest[] resourceArray = {
			// REFEREHCE : Google+ : https://developers.google.com/+/
			// People
			new RESTRequest("https://www.googleapis.com/plus/v1/people/%s", new String[] {ME}),
			new RESTRequest("https://www.googleapis.com/plus/v1/people?maxResults=20&query=%s", new String[] {ORGANIZATION}),
			new RESTRequest("https://www.googleapis.com/plus/v1/people/%s/activities/%s/?maxResults=100", new String[] {ME, PUBLIC}),

			// Activities
			new RESTRequest("https://www.googleapis.com/plus/v1/people/%s/activities/%s/?maxResults=100", new String[] {ME, PUBLIC}),
			new RESTRequest("https://www.googleapis.com/plus/v1/activities/%s", new String[] {ACTIVITY_ID}),
			new RESTRequest("https://www.googleapis.com/plus/v1/activities/?maxResults=20&query=%s", new String[] {ORGANIZATION}),

			// Comments
			new RESTRequest("https://www.googleapis.com/plus/v1/activities/%s/comments", new String[] {ACTIVITY_ID}),
			new RESTRequest("https://www.googleapis.com/plus/v1/comments/%s", new String[] {COMMENT_ID}),

		};

		// http://code.google.com/apis/gdata/faq.html#AuthScopes
		List<RESTRequest> requestList = new ArrayList<RESTRequest>();
		for(RESTRequest resource : resourceArray){
			requestList.add(resource);
		}

		// REFERENCE: "https://code.google.com/apis/console/
		this.apiProvider = "google";
		this.apiReference = "http://code.google.com/more/";
		this.apiClass = org.scribe.builder.api.GoogleApi.class;
		this.apiScopeList = scopeList;
		this.apiRequestList = requestList;
	}
}

Here is the listing for RESTRequest POJO which is extensively used

import java.util.Map;

import org.scribe.model.Verb;

public class RESTRequest {
	private Verb verb = null;
	private String url = null;

	private String parameters = null;
	private String payload = null;
	private Map<String, String> headers = null;

	private String[] variableValues = null;
	private boolean accessTokenRequired = true;

	public RESTRequest(String url){
		this(Verb.GET, url);
	}

	public RESTRequest(Verb verb, String url){
		this(verb, url, null);
	}

	public RESTRequest(String url, String[] variableValues){
		this(Verb.GET, url, variableValues);
	}

	public RESTRequest(Verb verb, String url, String[] variableValues){
		this(verb, url, true, variableValues);
	}

	public RESTRequest(String url, boolean accessTokenRequired, String[] variableValues) {
		this(Verb.GET, url, accessTokenRequired, variableValues);
	}

	public RESTRequest(Verb verb, String url, boolean accessTokenRequired, String[] variableValues){
		this.verb = verb;
		this.url = url;
		this.variableValues = variableValues;
		this.accessTokenRequired = accessTokenRequired;
	}

	public String toString(){
		return url;
	}

	public Verb getVerb() {
		return verb;
	}

	public void setVerb(Verb verb) {
		this.verb = verb;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String[] getVariableValues() {
		return variableValues;
	}

	public void setVariableValues(String[] variableValues) {
		this.variableValues = variableValues;
	}

	public boolean isAccessTokenRequired() {
		return accessTokenRequired;
	}

	public void setAccessTokenRequired(boolean accessTokenRequired) {
		this.accessTokenRequired = accessTokenRequired;
	}

	public void setParameters(String parameters) {
		this.parameters = parameters;
	}

	public String getParameters() {
		return parameters;
	}

	public String getPayload() {
		return payload;
	}

	public void setPayload(String payload) {
		this.payload = payload;
	}

	public Map<String, String> getHeaders() {
		return headers;
	}

	public void setHeaders(Map<String, String> headers) {
		this.headers = headers;
	}
}


1 Comment

5 Minutes on Java : XML Schema generation

I was constantly using an online XSD generator … however, recently I found that the site was hacked 😦 which forced to home brew a similar solution.

One of the Apache’s projects XMLBeans exactly does what I needed : http://xmlbeans.apache.org/

You can install the binaries, and take the xmlbean.jar for invoking API for conversion.  Here is a XMLBean wrapper that can be reused.

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;

import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.inst2xsd.Inst2Xsd;
import org.apache.xmlbeans.impl.inst2xsd.Inst2XsdOptions;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;

public class XMLBeans {
	public static void main(String[] args) {
		try {
			XMLBeans xmlBeans = new XMLBeans();
			SchemaDocument schemaDocument = xmlBeans.generateSchema(new File(
					"/Shared/test-data/test-data.xml"));

			StringWriter writer = new StringWriter();
			schemaDocument.save(writer, new XmlOptions().setSavePrettyPrint());
			writer.close();

			String xmlText = writer.toString();
			System.out.println(xmlText);

			System.out.println("Schemann" + xmlText);

		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public SchemaDocument generateSchema(File inputFile) throws XmlException,
	IOException {
		return generateSchema(inputFile, XMLSchemaDesign.VENETIAN_BLIND);
	}

	public SchemaDocument generateSchema(File inputFile, XMLSchemaDesign design)
			throws XmlException, IOException {
		// Only 1 instance is required for now
		XmlObject[] xmlInstances = new XmlObject[1];
		xmlInstances[0] = XmlObject.Factory.parse(inputFile);

		return inst2xsd(xmlInstances, design);
	}

	public SchemaDocument generateSchema(InputStream is, XMLSchemaDesign design)
			throws XmlException, IOException {
		// Only 1 instance is required for now
		XmlObject[] xmlInstances = new XmlObject[1];
		xmlInstances[0] = XmlObject.Factory.parse(is);

		return inst2xsd(xmlInstances, design);
	}

	public SchemaDocument generateSchema(String input) throws XmlException,
	IOException {
		return generateSchema(input, XMLSchemaDesign.VENETIAN_BLIND);
	}

	public SchemaDocument generateSchema(String input, XMLSchemaDesign design)
			throws XmlException, IOException {
		// Only 1 instance is required for now
		XmlObject[] xmlInstances = new XmlObject[1];
		xmlInstances[0] = XmlObject.Factory.parse(input);

		return inst2xsd(xmlInstances, design);
	}

	private SchemaDocument inst2xsd(XmlObject[] xmlInstances,
			XMLSchemaDesign design) throws IOException {
		Inst2XsdOptions inst2XsdOptions = new Inst2XsdOptions();
		if (design == null || design == XMLSchemaDesign.VENETIAN_BLIND) {
			inst2XsdOptions.setDesign(Inst2XsdOptions.DESIGN_VENETIAN_BLIND);
		} else if (design == XMLSchemaDesign.RUSSIAN_DOLL) {
			inst2XsdOptions.setDesign(Inst2XsdOptions.DESIGN_RUSSIAN_DOLL);
		} else if (design == XMLSchemaDesign.SALAMI_SLICE) {
			inst2XsdOptions.setDesign(Inst2XsdOptions.DESIGN_SALAMI_SLICE);
		}

		SchemaDocument[] schemaDocuments = Inst2Xsd.inst2xsd(xmlInstances,
				inst2XsdOptions);
		if (schemaDocuments != null && schemaDocuments.length > 0) {
			return schemaDocuments[0];
		}

		return null;
	}
}


Leave a comment

5 Minutes on Java : JSON to XML

You’ve hit this page because you are looking for this utility as I did today.  I wanted to convert JSON to XML in an easier way.  Thanks to http://openjsan.org/src/k/ka/kawasaki, who has implemented XML.ObjTree for performing JSON2XML conversion very elegantly.  All, I needed to do was to put in a Java wrapper.  Here is the XMLObjTree.java, a java wrapper for Kawasaki’s implementation.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

// A Java wrapper for XML.ObjTree
// Thanks to - http://openjsan.org/src/k/ka/kawasaki/XML.ObjTree-0.24/README
public class XMLObjTree {
    public static ScriptEngine getJsengine() {
		return jsEngine;
	}

	private static ScriptEngine jsEngine;

    static {
        try {
        	jsEngine = new ScriptEngineManager().getEngineByExtension("js");

        	InputStream is = XMLObjTree.class.getResourceAsStream("/scripts/js/XML/ObjTree.js");
        	InputStreamReader reader = new InputStreamReader(is);

        	jsEngine.eval(reader);

			is.close();
			reader.close();
		} catch (ScriptException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
    }

    public String jsonToXml(final File jsonFile) throws FileNotFoundException, IOException {
    	return (jsonToXml(StreamUtils.streamToString(jsonFile)));
    }

    public String jsonToXml(final InputStream is){
    	String input = StreamUtils.streamToString(is);

    	return (jsonToXml(input));
    }

    public String jsonToXml(final String jsonText) {
        try{
            return (String) jsEngine.eval("(new XML.ObjTree()).writeXML(" + jsonText + ");");
        }
        catch(ScriptException ex) {
            throw new RuntimeException(ex);
        }
    }
}

Here is the StreamUtils  you’ll need

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;

public class StreamUtils {
	public static String streamToString(InputStream is) {
		try
		{
			final char[] buffer = new char[4096];
			StringBuilder out = new StringBuilder();

			Reader in = new InputStreamReader(is, "UTF-8");

			int read;
			do
			{
				read = in.read(buffer, 0, buffer.length);
				if (read > 0)
				{
					out.append(buffer, 0, read);
				}
			} while (read >= 0);

			in.close();

			return out.toString();
		} catch (IOException ioe)
		{
			throw new IllegalStateException("Error while reading input stream", ioe);
		}
	}

	public static String streamToString(File file) throws FileNotFoundException, IOException {
		FileInputStream fis = new FileInputStream(file);

		String string = streamToString(fis);
		fis.close();

		return string;
	}

	public static void write(final String data, final Writer writer) throws IOException{
		writer.write(data);

		writer.flush();

		writer.close();
	}

	public static void write(final String data, final File file) throws IOException{
		try{
			FileOutputStream fos = new FileOutputStream(file);

			Writer writer = new OutputStreamWriter(fos, "UTF-8");
			write(data, writer);

			fos.close();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
		}
	}
}

Let’s put it to use using some sample JSON text

    public static void main(String[] args){
		final String filePath = "/Shared/test-data/test-data.json";
		final File jsonFile = new File(filePath);

		try {
			XMLObjTree xmlObjTree = new XMLObjTree();

			System.out.println("XMLnn" + xmlObjTree.jsonToXml(jsonFile));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


11 Comments

5 Minutes on Java: GWT consumer + Server push tutorial

The previous 2 posts on server push demonstrated the idea of push information to the consumers with Java services and Flex client. However, many might argue that a generic consumer should work on any device and it is better to develop and support such framework.  In an environment where rapid prototyping is the key driver, with a responsibility to drive development frameworks and technologies; the constraints can be many.

On that pretext, I tried GWT framework to see if we can do things quickly and effectively as done with Flash, and I find it to be promising in many ways.

  • It generates JavaScript which is compact and optimized and can be obfuscated.
  • Can run on various browsers and platforms.
  • Development cost can be reduced as most enterprise developers are experienced in Java.
  • At the same time, can create proof-of-concepts quickly and efficiently.

However, one challenge I faced was getting the right blend of components to work with GWT.  Firstly, I tried ActiveMQ AJAX, which was good to begin with, however, when working with JQuery libraries, JavaScript really messes up the namespaces.  Secondly, was trying hard to see if Comet can save the day, but only in vain.  It became more messier as libraries were incompatible with some of the third-party components required in the backend.

After a lot of thoughts and architectural considerations, I finally decided to reuse most of the work done on the back-end (which is critical); which happens to be ActiveMQ (FUSE); Yet had to give up the idea of Flash moving forward; this  became a key driver for future; which means that rapid prototyping must be supported as a fundamental requirement, at the same time keeping the technology stack for building prototypes and learning curve as lean as possible.

Applications, be it RESTful or Presence based, it must inter-operate, change and grow with changing requirements.  So how do we put all of these together?

  • Jersey/Restlet fits the stack perfectly for exposing RESTful API
  • ActiveMQ becomes a preferred choice for messaging; which is scalable and reliable as well.

Bring them together with GWT for HTML(5) client, and stage is set for developing applications for the future.  There are challenges with data-binding that you’ll miss if you’re used to Adobe Flex a lot.  In my opinion that could be solved in few years.

Having said enough so far, let’s see the sample code to make this work with GWT; I used GWT Eventing to implement message handling on the client.

Download it from gwteventservice google code

Make sure you have the following inherits in *.gwt.xml file.

<inherits name='com.google.gwt.user.User' />
<inherits name='com.google.gwt.xml.XML' />
<inherits name='de.novanic.eventservice.GWTEventService' />

Add the following files to your gwt client package.
File: MessengerRemoteService

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

import de.novanic.eventservice.client.event.domain.Domain;
import de.novanic.eventservice.client.event.domain.DomainFactory;

@RemoteServiceRelativePath("MessengerRemoteService")
public interface MessengerRemoteService extends RemoteService {
	public static final Domain SERVER_MESSAGE_DOMAIN = DomainFactory.getDomain("server_message_domain");

	/**
	 * Utility class for simplifying access to the instance of async service.
	 */

	public void start();

	public static class Util {
		private static MessengerRemoteServiceAsync instance;
		public static MessengerRemoteServiceAsync getInstance(){
			if (instance == null) {
				instance = GWT.create(MessengerRemoteService.class);
			}
			return instance;
		}
	}
}

File: MessengerRemoteService

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface MessengerRemoteServiceAsync {
	void start(AsyncCallback<Void> callback);
}

File: MessageEvent

import de.novanic.eventservice.client.event.Event;

public class MessageEvent implements Event {
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	protected String message = null;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public MessageEvent(String message){
		super();

		this.message = message;
	}

	public MessageEvent(){}
}

Finally, add the code to your entry point that will load the EventListener. This code will be the main event receiver, hence should be able use this to receive events from the server and let the visualization component render it based on the views.

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.xml.client.DOMException;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.XMLParser;

import de.novanic.eventservice.client.event.Event;
import de.novanic.eventservice.client.event.RemoteEventService;
import de.novanic.eventservice.client.event.RemoteEventServiceFactory;
import de.novanic.eventservice.client.event.listener.RemoteEventListener;

public class ConnectorSample {
	public void connect(){
		RemoteEventService remoteEventService = RemoteEventServiceFactory.getInstance().getRemoteEventService();
		remoteEventService.addListener(MessengerRemoteService.SERVER_MESSAGE_DOMAIN,
			new RemoteEventListener() {
				@Override
				public void apply(Event anEvent) {
					if(anEvent instanceof MessageEvent){
						String message = ((MessageEvent)anEvent).getMessage();

						try {
							NodeList nodes = null;

							try {
								Document messageDocument = XMLParser.parse(message);
								nodes = messageDocument.getElementsByTagName("some tag name");
							}catch(DOMException domex){
								throw new Exception("XMLParseException while parsing message");
							}

							if(nodes != null && nodes.getLength() > 0){
								for(int index = 0; index < nodes.getLength(); index++){
									Element element = (Element) nodes.item(index);

									// Update DataModel
									// Updae View

								}
							}
						}
						catch(Exception e){
							GWT.log(e.getMessage());
						}
					}
				}
			}
		);

		MessengerRemoteService.Util.getInstance().start(new VoidAsyncCallback());
	}

	private class VoidAsyncCallback implements AsyncCallback<Void>
    {
        public void onFailure(Throwable aThrowable) {}

        public void onSuccess(Void aResult) {}
    }
}

Add the following file to your gwt server package
File: MessengerRemoteService

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.apache.activemq.command.ActiveMQTextMessage;
import org.onesun.sfs.client.MessengerRemoteService;
import org.onesun.sfs.shared.event.MessageEvent;

import de.novanic.eventservice.client.event.Event;
import de.novanic.eventservice.service.RemoteEventServiceServlet;

public class MessengerRemoteServiceImpl extends RemoteEventServiceServlet
	implements MessengerRemoteService, MessageListener
{
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	public void init(){
	}

	@Override
	public void start() {
	}

	private void sendToClient(Event event){
		addEvent(MessengerRemoteService.SERVER_MESSAGE_DOMAIN, event);
	}

	@Override
	public void onMessage(Message message) {
		String messageText = null;
		try {
			messageText = ((TextMessage)message).getText();
		} catch (JMSException e) {
			e.printStackTrace();
		}

		if(messageText != null && messageText.length() > 0){
			if(message instanceof ActiveMQTextMessage) {
				sendToClient(new MessageEvent(messageText));
			}
		}
	}
}

Now connect the code with configurations for the Web App to work well.

  <servlet>
    <servlet-name>EventService</servlet-name>
    <servlet-class>
      de.novanic.eventservice.service.EventServiceImpl
    </servlet-class>
  </servlet>

  <servlet>
  	<servlet-name>MessengerRemoteService</servlet-name>
  	<servlet-class>PACKAGE_NAME.MessengerRemoteServiceImpl</servlet-class>
  </servlet>

  <servlet-mapping>
  	<servlet-name>MessengerRemoteService</servlet-name>
  	<url-pattern>/feedvu/MessengerRemoteService</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>EventService</servlet-name>
    <url-pattern>/feedvu/gwteventservice</url-pattern>
  </servlet-mapping>

Update the applicationcontext.xml for spring injections

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jms="http://www.springframework.org/schema/jms"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:s="http://www.springframework.org/s"
	xmlns:context="http://www.springframework.org/schema/context"

	xsi:schemaLocation="http://www.springframework.org/schema/beans
 		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 		http://www.springframework.org/schema/context
 		http://www.springframework.org/schema/context/spring-context-2.5.xsd
 		http://www.springframework.org/schema/jms
 		http://www.springframework.org/schema/jms/spring-jms-2.5.xsd
 		http://www.springframework.org/schema/util
 		http://www.springframework.org/schema/util/spring-util-2.0.xsd
 		http://camel.apache.org/schema/spring
 		http://camel.apache.org/schema/spring/camel-spring.xsd">

	<camelContext xmlns="http://camel.apache.org/schema/spring" />

	<!-- ActiveMQ JMS -->
	<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
		p:brokerURL="tcp://localhost:61616" />

	<jms:listener-container container-type="default" destination-type="topic" connection-factory="connectionFactory" acknowledge="auto">
		<jms:listener destination="feed-message-topic" ref="messengerRemoteService" method="onMessage" />
	</jms:listener-container>

	<bean id="messengerRemoteService" init-method="init" class="PACKAGE_NAME.MessengerRemoteServiceImpl">
	</bean>
</beans>

Finally startup the services and send messages to the topic using FUSE admin, the GWT client should render the messages as they are pushed on the Bus.

Summary and some thoughts:

Flash will still remain a way to quickly develop proof-of-concepts.  It provides a way to seamlessly bind data and visualization.  It is good to turn vapor-ware thoughts into tangible concepts; which is a good proposition in a life-cycle of prototyping.

On the other hand, if I were to build concepts that need to work on non-flash devices; then have to look into GWT like frameworks (since coming from Java world).  There are challenges with data-binding to visualization, rendering of changing data can be challenging.  HTML5 features of client side storage can help to build tactics on the client to resolve certain limitations.

In either case, depending on the time available, features of the application, and the case to demonstrate on diverse platforms, you can decide one over the other.

Server Push is essential for messaging; and clients must be built with the future in mind.  I’m sure you’ll find the samples for both frameworks simple and reusable.


Leave a comment

5 Minutes on Java: Creating a JMS producer with Camel and FUSE frameworks

In the previous post I demonstrated how to quickly create a server push application.  However, the previous post deliberately avoided the producer component.  In this post we’ll create a producer totally de-coupled from the consumer. I like this approach because, the clients need not be developed within the producer context.

What you’ll need?

  • Spring: for injecting beans (avoid writing boiler plate code)
  • Apache Camel: enable routing and manage messaging infrastructure
  • FUSE: message broker

Create a Java project.

You’ll require the following jar files.

        org.springframework.asm-3.0.3.RELEASE.jar
        org.springframework.beans-3.0.3.RELEASE.jar
        org.springframework.context-3.0.3.RELEASE.jar
        org.springframework.context.support-3.0.3.RELEASE.jar
        org.springframework.core-3.0.3.RELEASE.jar
        org.springframework.jdbc-3.0.3.RELEASE.jar
        org.springframework.transaction-3.0.3.RELEASE.jar
        log4j-1.2.15.jar
        commons-lang-2.4.jar
        commons-codec-1.4.jar
        commons-logging-1.1.1.jar
        org.springframework.expression-3.0.3.RELEASE.jar
        commons-dbcp-1.4.jar
        commons-pool-1.5.4.jar
        slf4j-log4j12-1.5.10.jar
        slf4j-api-1.5.10.jar
        camel-core-2.4.0.jar
        camel-jetty-2.4.0.jar
        camel-jms-2.2.0.jar
        camel-spring-2.4.0.jar
        commons-discovery-0.2.jar
        commons-io.jar
        commons-management-1.0.jar
        org.springframework.aop-3.0.3.RELEASE.jar
        org.springframework.jms-3.0.3.RELEASE.jar
        activemq-all-5.4.0-fuse-00-00.jar

Create a applicationContext.xml and add the following beans

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jms="http://www.springframework.org/schema/jms"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:s="http://www.springframework.org/s"
	xmlns:context="http://www.springframework.org/schema/context"

	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

	<!-- ActiveMQ JMS -->
	<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
		p:brokerURL="tcp://localhost:61616" />

	<jms:listener-container container-type="default"
		destination-type="topic" connection-factory="connectionFactory"
		acknowledge="auto">
	</jms:listener-container>

	<camelContext xmlns="http://camel.apache.org/schema/spring">
	</camelContext>

	<!-- Producer -->
	<bean id="messageProducer" class="org.onesun.camel.test.MessageProducer" init-method="init">
		<property name="topic" value="jms:topic:flex-client-broadcast-topic" />
	</bean>

	<bean id="clientProxy" class="org.onesun.camel.test.CamelTestApp">
		<property name="messageProducer" ref="messageProducer" />
	</bean>
</beans>

The connectionFactory bean references the FUSE ActiveMQ broker endpoint to which the application must bind to.  the listener container uses the connectionFactory to create a default route to topics and finally, the camelContext activates the beans and the endpoints.  These three definitions are essential for interconnecting FUSE, JMS and Camel, with this we’re now ready to write a simple producer.

package org.onesun.camel.test;

import org.apache.camel.EndpointInject;
import org.apache.camel.InOnly;
import org.apache.camel.ProducerTemplate;
import org.apache.log4j.Logger;

@InOnly
public class MessageProducer {
	private static Logger logger = Logger.getLogger(MessageProducer.class);
	protected String topic = null;

	@EndpointInject
	protected ProducerTemplate producer;

	public void init(){
		logger.info(MessageProducer.class + " initialized");
	}

	public void send(String message) {
		producer.sendBody(topic, message);
	}
	public String getTopic() {
		return topic;
	}
	public void setTopic(String topic) {
		this.topic = topic;
	}
}

The MessageProducer bean provides interface to send message to a topic. Now we can create the main program that will publish messages onto the topic.

package org.onesun.camel.test;

import java.util.Date;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class CamelTestApp {
	private static ApplicationContext context = null;

	private static MessageProducer messageProducer = null;

	public static MessageProducer getMessageProducer() {
		return messageProducer;
	}

	public void setMessageProducer(MessageProducer messageProducer) {
		ClientProxy.messageProducer = messageProducer;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Load Spring
		if (context == null) {
			context = new ClassPathXmlApplicationContext("applicationContext.xml");
		}

		for(int index = 0; index < 10; index++){
			messageProducer.send(
				"<item><label>" +
				new Date() +
				"</label></item>"
			);
		}
	}
}

With this application running you should see the dates appear on the flex sample or any other consumer application.  Good luck fusing together frameworks and riding the Camel.

This example has been tested and validated on Linux and Windows.


Leave a comment

5 Minutes on Java – A template implementation for configuration files

Loading properties or configurations for applications is a common task.  The process is generic and repeatable.  The following template implementation should provide an easy way to extend it based on application needs.

The design:

  • Template class: implements the algorithm and automates the process of initialising and loading/saving configuration files.
  • Implementation classes
  • A factory approach to consume all the implementations.

An Implementation

 public class Test{
 public static void main(String[] args) {
 PropertyFilesFactory.init();
 Properties properties = PropertyFilesFactory.getProperties("db");
 System.out.println("Testing: " + properties.getProperty("DB_MAX_CONNECTIONS"));
 }
 public class PropertyFilesFactory {

private static HashMap props = new HashMap();

public static void init(){

if(props.size() == 0){

// Create Configuration
 props.put("app", new AppPropertiesFileLoader());
 props.put("log", new LoggerPropertiesFileLoader());
 props.put("db" new IMDBPropertiesFileLoader());

// initialize configuration
 for(PropertiesFileTypes key : props.keySet()){
 props.get(key).init();

}

// post initialization
 for(PropertiesFileTypes key : props.keySet()){

props.get(key).postinit();

}

}

private static PropertiesFileLoader getConfig(String ct)

return props.get(ct);

}

public static Properties getProperties(String ct){

if(ct == null) return null;
 else return getConfig(ct).getProperties();

}

}

The Algorithm


package ez.cfg;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

import org.apache.log4j.Logger;

import ez.util.Constants;
import ez.util.Utility;

public abstract class PropertiesFileLoader {
 private static final Logger logger = Logger.getLogger(PropertiesFileLoader.class.getName());

 protected boolean justCreated = false;
 protected boolean initialized = false;
 protected Properties properties = new Properties();
 protected String fileName = "";

 public PropertiesFileLoader(String fileName){
 this.fileName = fileName;

 preinit();
 }

 // Mandatory: Client must override;
 abstract public void setup();

 // hook: client may not override unless needed
 public void postinit() {}

 public void preinit() {
 // Create Configdir
 File f = new File(Constants.CONFIG_DIR);
 if(f.exists() == false) {
 f.mkdir();
 }
 }

 // Can't override
 public final void init(){
 if(Utility.exists(fileName) == true){
 load();
 }
 else {
 justCreated = true;
 setup();

 save();

 load();
 }
 }
 synchronized final public void save(){
 File f = new File(fileName);
 FileOutputStream fos = null;

 try {
 fos = new FileOutputStream(f);
 if(properties.size() > 0){
 properties.store(fos, "");
 }
 else {
 logger.debug("Properites not setup, not writing to file!");
 }
 } catch (Exception e) {
 logger.error("Error while loading configuration: " + fileName);
 e.printStackTrace();
 } finally {
 try {
 if(fos != null) fos.close();

 if(justCreated == true){
 System.err.println("Config file " + fileName + " was just created, please fill it up before proceeding!");
 System.exit(1);
 }
 } catch (IOException e) {
 logger.error("Error while closing configuration: " + fileName);
 e.printStackTrace();
 }
 }
 }

 public final void load(){
 FileInputStream fis = null;

 try {
 File f = new File(fileName);
 fis = new FileInputStream(f);
 properties.load(fis);

 initialized = true;
 } catch (Exception e) {
 logger.error("Error while loading configuration: " + fileName);
 e.printStackTrace();
 } finally {
 try {
 if(fis != null) fis.close();
 } catch (IOException e) {
 logger.error("Error while closing configuration: " + fileName);
 e.printStackTrace();
 }
 }
 }

 public final Properties getProperties() {
 return properties;
 }

 public final boolean isInitialized(){
 return initialized;
 }

 public final boolean wasJustCreated() {
 return justCreated;
 }
}

Specialization for DataBase Configuration


package ez.cfg;

import java.io.File;

import ez.util.Constants;

public class IMDBPropertiesFileLoader extends PropertiesFileLoader {
 private static final String IMDB_CONFIG_FILE = Constants.CONFIG_DIR + File.separatorChar + "db.properties";

 public IMDBPropertiesFileLoader(){
 super(IMDB_CONFIG_FILE);
 }

 @Override
 public void setup(){
 properties.setProperty(Constants.DB_DRIVER_CLASS, "org.hsqldb.jdbcDriver");
 properties.setProperty(Constants.DB_URL, "jdbc:hsqldb:mem:feed_content_db");
 properties.setProperty(Constants.DB_USER, "sa");
 properties.setProperty(Constants.DB_PASSWORD, "");
 properties.setProperty(Constants.DB_MAX_CONNECTIONS, "2");
 }
}

Specialization for Logger Configuration


package ez.cfg;

import java.io.File;

import org.apache.log4j.PropertyConfigurator;

import ez.util.Constants;

public class LoggerPropertiesFileLoader extends PropertiesFileLoader {
 private static final String LOGGER_CONFIG_FILE = Constants.CONFIG_DIR + File.separatorChar + "logger-config.properties";

 public LoggerPropertiesFileLoader(){
 super(LOGGER_CONFIG_FILE);
 }

 @Override
 public void setup(){
 properties.setProperty("log4j.rootLogger", "debug, FILE");
 properties.setProperty("log4j.appender.FILE", "org.apache.log4j.FileAppender");
 properties.setProperty("log4j.appender.FILE.layout", "org.apache.log4j.PatternLayout");
 properties.setProperty("log4j.appender.FILE.File", "logs/diagnostic.log");
 properties.setProperty("log4j.appender.FILE.layout.ConversionPattern", "%d{ABSOLUTE} %5p %c{1}:%L - %m%n");
 }

 @Override
 public void postinit(){
 PropertyConfigurator.configure(properties);
 }
}

Constants used


package ez.util;

import java.io.File;

public interface Constants {
 public static final String CONFIG_DIR = "config";
 public static final String DATA_DIR = "data";
 
 public static final String HTTP_TIMEOUT = "HTTP_TIMEOUT";
 public static final String OUTPUT_FILE_STORE = "OutputFileStore";
 

 public static final String DB_DRIVER_CLASS = "JDBC.DRIVER";
 public static final String DB_USER = "USER";
 public static final String DB_PASSWORD = "PASSWORD";
 public static final String DB_MAX_CONNECTIONS = "CONNECTIONS";
 public static final String DB_URL = "JDBC.URL";
}