How To Define a Spring Bean With Generics Parameter

At the time when this article was written, the Spring framework does not allow to define beans in application context xml file using parameterized classes. The reason for that is that generics parameters are compiler information, and not run-time. Compiler information is something that Spring does not care about. For example, the following (or something similar) will NOT work:

<bean id="someClass" class="asia.javabeans.SomeClass<asia.javabeans.Blah>"  />

Sometimes, this restriction can create a problem if you have a parameterized class that has to be loaded by Spring. As a workaround, create an empty child class that extends your parameterized class, and then use that class’s canonical name as your bean definition. Consider the following parameterized parent and the extending child classes:

public class SomeParent<Blah> {

}

public class Child extends SomeParent<Blah> {
   // Just an empty class
}

and your Spring definition can now look like this:

<bean id="childClass" class="asia.javabeans.Child" />

The down side here is that you get stuck with an empty class, but at least you can have your bean definition in your application context xml file.

Web Applications with AJAX, Servlets and JSON (Chinese Version)

在这篇文章中,我想说明如何的JSON(JavaScript对象
符号)和Java Servlet可以同时使用在一个小的AJAX((Asynchronous JavaScript and XML)的应用。

为了作简要介绍那些谁不熟悉使用JSON密切。JSON是一种表示数据,这使得工作轻量级语法
它比更愉快,使AJAX应用程序的XML 快。此外,当使用JSON工作,没有任何一个XML需要
解析。

在下面的例子,我将创建一个回调的servlet 获取并分析了RSS提要。然后解析数据被传递到饲料
在一个客户端JSON的形式。这些数据然后格式化并提交 给用户。客户端使用AJAX调用来查询的servlet。

对于这种应用,我使用了三个第三方库:

图书馆提供的JSON和JSON的JSON.org – RPC的Java的,允许以建立并轻松地通过Java代码解析JSON数据延长。该库可以运行在一个如Tomcat,JBoss和其他J2EE应用服务器的Servlet容器。

项目罗马
罗马是一个开放源码的Java工具,用于分析,生成和发布RSS和Atom馈送。

JDOM的XML解析器
JDOM是一个基于Java的“文档对象模型的XML文件”。 JDOM的服务作为DOM的相同目的,但更容易使用

这些库中包含的源代码,附带这篇文章。此应用程序的例子还包括作为一个WAR档案,随时可以在Tomcat部署。
以下是我的servlet实现。该servlet饲料获取并分析数据。前面提到的JSON库让我轻松地创建和填充JSON对象。

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.fetcher.FeedFetcher;
import com.sun.syndication.fetcher.FetcherException;
import com.sun.syndication.fetcher.impl.FeedFetcherCache;
import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache;
import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;
import com.sun.syndication.io.FeedException;

/**
* @author Alexander Zagniotov (http://javabeans.asia)
*/
public class JsonServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static final String BLOG_URL = "http://javabeans.asia/rss.xml";
	private static final String CONTENT_TYPE = "application/json";
	private FeedFetcherCache feedInfoCache = null;
	private FeedFetcher feedFetcher = null;

	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		feedInfoCache = HashMapFeedInfoCache.getInstance();
		feedFetcher = new HttpURLFeedFetcher(feedInfoCache);
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		SyndFeed feed = this.feedFethcer(BLOG_URL);
		if (feed != null) {
			String json = this.feedToJSON(feed);
			response.setContentType(CONTENT_TYPE);
			response.setHeader("Cache-Control", "no-cache");
			response.getWriter().write(json);
		}
	}

	private SyndFeed feedFethcer(String url) {
		SyndFeed feed = null;
		try {
			feed = feedFetcher.retrieveFeed(new URL(BLOG_URL));
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (FeedException e) {
			e.printStackTrace();
		} catch (FetcherException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return feed;
	}

	private String feedToJSON(SyndFeed feed) {

		JSONObject jsonObj = new JSONObject();
		JSONArray jsonEntryTitles = new JSONArray();
		jsonObj.put("blogtitle", feed.getTitle());
		jsonObj.put("blogdescription", feed.getDescription());
		jsonObj.put("bloglanguage", feed.getLanguage());
		jsonObj.put("bloglink", feed.getLink());
		jsonObj.put("author", feed.getCopyright());

		List<?> feedEntries = feed.getEntries();

		for (Object c : feedEntries) {
			SyndEntry syndicateEntry = (SyndEntry) c;
			jsonEntryTitles.put(syndicateEntry.getTitle());
		}

		jsonObj.put("blogentrytitles", jsonEntryTitles);
		return jsonObj.toString();
	}
}

正如你可以看到它是很容易的构建在服务器端JSON对象和数组并传递给客户端。对于本示例的目的,我从RSS饲料得到我的数据,但数据也可从数据库等来

以下是我的客户端实现。客户端的servlet查询使用AJAX调用。当一个AJAX调用返回从一个JSON的Servlet的响应对象的形式,对象数据的格式以及有关的RSS供稿信息呈现给客户端:

<html>
    <head>
    <title>Java Beans dot Asia</title>

    <script language="JavaScript" type="text/javascript">

        var httpRequest = null;

    function getDescriptionAsJSON() {
        var description = document.getElementById('description');
        description.innerHTML = "Loading, please wait ...";

        var url = "http://localhost:8080/json/json";
        if(window.XMLHttpRequest){
            httpRequest = new XMLHttpRequest();
        } else if(window.ActiveXObject){
            httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        }

        httpRequest.open("GET", url, true);
        httpRequest.onreadystatechange = handler;
        httpRequest.send(null);
    }

    function handler() {
        if (httpRequest.readyState == 4) {
            if (httpRequest.status == 200) {
                processJSON(httpRequest.responseText);
            }
        }
    }

    function processJSON(jsonObjectString) {

        var description = document.getElementById('description');

        //Since JSON is a subset of JavaScript, I am using
        //JavaScript's own compiler to parse JSON in one line!

        var jsonObject = eval('(' + jsonObjectString + ')')
        var text = "";

        text += "Author: " + jsonObject.author + "< br />";
        text += "Blog Name: " + jsonObject.blogtitle + "< br />";
        text += "Blog URL: " +    jsonObject.bloglink + "< br />";
        text += "Blog Description: " +    jsonObject.blogdescription + "< br />";
        text += "Blog Language: " + jsonObject.bloglanguage + "< br />";

        description.innerHTML = text;
        var entries = "Last " + jsonObject.blogentrytitles.length + " blog entries are:nn";

        for (var index = 0; index < jsonObject.blogentrytitles.length; index ++) {
            entries += (index + 1) + ": " + jsonObject.blogentrytitles[index] + "n";
        }
        alert(entries);
    }

    </script>

    </head>
    <body>
        <img src="images/javabeansmugshot_120x120.jpg" border="1" />< br />< br />
        <div id="description"></div>< br />< br />
        <a href="javascript:void(0)" onclick="return getDescriptionAsJSON();">Click to get description!</a>
    </body>
</html>

正如你可以看到,JSON数据可以很容易地解析对与Java的脚本eval()函数帮助客户端。为了提醒 – JSON是一个Java脚本的一个子集,因此的eval()将产生一个有效的对象。

请记住,有一个额外需要照顾时,使用eval。问题是,试用版本将编译并执行Java脚本代码,回来从响应。这可能导致安全风险,如果响应数据是来自不可信来源的到来。

就是这样。我希望这个例子是明确的和有用的:)

source code json and servlets

请注意,这个例子是我和测试其工作的罚款。源代码是因为前面提到的Eclipse项目中。你可以简单地创建一个从现有的Ant build.xml文件新的Java项目。

评论表示赞赏:)

干杯

Hibernate Event Interceptor

Its quite common when you create an application, there is a need to create an audit trail on the application level where all entity insert, update and delete events are logged.

In this post, I would like to describe a simple approach that can help you to avoid littering with unnecessary statements in your application code. The solution is to register a class as a listener on Hibernate events. Once class is triggered, you will be able to write audit information to a database or log file.

The following shows a Hibernate event interceptor class that is triggered when persistent entity is inserted, deleted or updated.

public class HibernateEventInterceptor	implements	PostInsertEventListener,
							PostUpdateEventListener,
							PostDeleteEventListener,
							Initializable {

	public HibernateEventInterceptor() {

	}

	public void initialize(Configuration cfg) {

	}

	public void onPostInsert(PostInsertEvent event) {
		String entityName = event.getPersister().getEntityName();
		System.out.println("Inserted entity: " + entityName);
	}

	public void onPostUpdate(PostUpdateEvent event) {
		String entityName = event.getPersister().getEntityName();
		System.out.println("Updated entity: " + entityName);
	}

	public void onPostDelete(PostDeleteEvent event) {
		String entityName = event.getPersister().getEntityName();
		System.out.println("Deleted entity: " + entityName);
	}
}

The following shows extra configuration that must be added to persistence.xml, in order for the interceptor class to be triggered:

<persistence>
	<persistence-unit name="org.example.demo">
	<jta-data-source>java:/test</jta-data-source>
		<properties>
			.
			.
			.
		<property name="hibernate.ejb.event.post-insert" value="org.example.demo.HibernateEventInterceptor"/>
		<property name="hibernate.ejb.event.post-update" value="org.example.demo.HibernateEventInterceptor"/>
		<property name="hibernate.ejb.event.post-delete" value="org.example.demo.HibernateEventInterceptor"/>
		</properties>
	</persistence-unit>
</persistence>

Bitwise Operation In Hibernate 3

Hi all…
i encountered a small problem in doing bitwise operations with hibernate. Until now, HIbernate 2 HQL parser has supported bitwise operations. Hibernate 3 for some reason does not support it. So if you want to work around it, you have to create a custom SQLfunction and add it to the dialect, that will map the bitwise operator.

You have to create your own class, which will extend from StandardSQLFunction class and will implement SQLFunction interface. You have to override render() method from the interface mentioned before and provide your own implementation.

In my example I am showing how to use ampersand symbol (‘&’) for bitwise operation.

Important note:
Hibernate team people have changed SQLFunction interface when upgrading from version 3.0.2 to 3.0.3, so your custom implementation of bitwise operation in version 3.0.2 will not work in 3.0.3. So keep that in mind.

Update (13.Jan.2010):
According to one of the blog reader’s this example has successfully worked under Hibernate v.3.2.6!

Implementation:
I am using Sysbase dialect, so i will create a class that extends this dialect with my own implementation:

package com.project.test.dialect;

import org.hibernate.Hibernate;

public class SybaseDialect extends
	org.hibernate.dialect.SybaseDialect{

	public SybaseDialect() {
	   super();
	   registerFunction("bitwise_and",
		new BitwiseAndFunction("bitwise_and",
				Hibernate.INTEGER));
	} 

}

What it means basically that i am registering a function by the name of bitwise_and the return type will be of type Integer.

Now, my custom class for SQLFunction like this:

package com.project.test.dialect;

import java.util.List;

import org.hibernate.QueryException;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.type.Type;

public class BitwiseAndFunction
		extends StandardSQLFunction
			 implements SQLFunction {

 public BitwiseAndFunction(String name) {
		super(name);
 }

 public BitwiseAndFunction(String name, Type type) {
	super(name, type);
 }

 public String render(List args,
	SessionFactoryImplementor factory)
			throws QueryException {
   if (args.size() != 2) {
      throw new IllegalArgumentException(
	"the function must be passed 2 arguments");
   }
   StringBuffer buffer = new
	StringBuffer(args.get(0).toString());
   buffer.append(" & ").append(args.get(1));
   return buffer.toString();
 }
}

The method render() accepts two arguments, if less – exception will be thrown. Once arguments are passed to the method, it will return a String that will look something like this (assuming that the passed arguments were one (1) and two (2)):

1 & 2

In my project, I am using named queries in my hbm.xml files, so below you can see a part of my hbm.xml file where I use my bitwise function:

<query name="UserPermissionsForEnttiy">
select object(ep) from EntityPermission ep where ep.userid =
:userid and ep.entityid = :entityid and ep.classname =
:classname and bitwise_and(ep.permission,:requiredpermission) > 0
</query>

Note the two arguments that i am passing to the bitwise_and function.

Also not forget to update your persistence XML with your custom dialect class, this is how my persistence.xml looks like:

<persistence>
<persistence-unit name="com.project.test.users">
<jta-data-source>java:/DefaultDS</jta-data-source>
   <properties>
   <property name="hibernate.dialect"
	value="com.project.test.dialect.SybaseDialect"/>
   <property name="hibernate.hbm2ddl.auto"
	value="update"/>
   <property name="hibernate.show_sql"
	value="true"/>
	   .
	   .
	   .
   </properties>
</persistence-unit>
</persistence>

Please note the hibernate.dialect property. As a value i gave the canonical name of my custom SysbaseDialect class.

Once you finished implementing your custom dialect classes, you can JAR them and put into the lib directory of your JBoss instance where the rest of your Hibernate libraries are.

Do not forget to restart your JBoss – it needs to load your newly added JAR, for you to be able to use it ;)

Using Template to Deploy a JBoss Queue

Currently I am involved in a project, where I have to use Velocity template engine to deploy queues and message-driven beans to JBoss. Velocity is a template engine that can be used for many purposes, and in my case I am using it to generate XML descriptor for a JBoss queue, hence: some-queue-name-service.xml. Its a simple scripting language and the XML descriptor template looks quite similar to the resulting XML descriptor.

Why do we use a template for deployment?
Because some of our deployments occur at runtime, where properties for the queues and MDB’s are generated on the fly and we need a templating engine to be able generate the deployments.

So i decided to describe a process of deploying a JBoss queue. I am hoping that I will be clear enough, since i am quite new to this my self.

The setup of my system:

/opt/mitto/jboss/server/mitto/

Root directory for my JBoss instance. (the [.])

My Velocity templates sit under the root, inside dynamic-templates directory:

./dynamic-templates/

JBoss deployment service will look under the root of my JBoss instance for the dynamic-templates directory.

JBoss deployment service depends on Velocity library (velocity.jar) that must be included under the root of:

./deploy/deployment-service.sar/

XML descriptor of JBoss deployment service (jboss-service.xml) sits under:

./deploy/deployment-service.sar/META-INF/

You can see below the jboss-service.xml:

	<mbean code="org.jboss.services.deployment.DeploymentService" name="jboss:service=DeploymentService">
		<attribute name="TemplateDir">dynamic-templates</attribute>
		<attribute name="DeployDir">dynamic-deploy</attribute>
		<attribute name="UndeployDir">dynamic-undeploy</attribute>
	</mbean>

The three directories mentioned above in jboss-service.xml, sit under the root of my JBoss instance.
TemplateDir – where my deployment generation templates can be found.
UndeployDir – the generated modules go there.

DeployDir – the directory to use when I ask to deploy a generated module.

Now, inside the:

./dynamic-templates/

I have following structure:

	jbossmessaging-queue/
		            /vm/
		               jbossmessaging-queue.xml.vm
		            template-config.xml

jbossmessaging-queue – directory that contains Velocity XML descriptor template for my queue. Also it represents the name of the deployment template that should be used, when createModule() method of deployment service will be called.

template-config.xml specifies the properties for Velocity template XML descriptor for our queue. Deployment service will be able to access those properties when rendering the Velocity template and to retrieve the values of JNDIName and QueueName properties.

Below you can see the descriptor for the template-config.xml:

	<template-config template="vm/jbossmessaging-queue.xml.vm" extension="-service.xml">
		<property-list>
		<property name="QueueName" type="java.lang.String" optional="false"/>
		</property-list>
	</template-config>

jbossmessaging-queue.xml.vm mentioned above, is the name of the actual Velocity template XML descriptor for the queue, which you can see below:

	<?xml version="1.0" encoding="UTF-8"?>
	<!--  ===================  QueueName - $QueueName ======= -->
	<server>
		<mbean code="org.jboss.jms.server.destination.QueueService"
						name="jboss.messaging.destination:service=Queue,
						name=$QueueName" xmbean-dd="xmdesc/Queue-xmbean.xml">

		<depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
		<attribute name="Clustered">true</attribute>
		<depends>jboss.messaging:service=PostOffice</depends>
		</mbean>
	</server>

Implementation:
I created a service bean that will acquire proxies for the JBoss MainDeployerMBean and JBoss DeploymentServiceMBean. I will use JBoss deployment service to construct a queue module in the file system, and I will use JBoss main deployer to deploy the queue, by pointing it to the module in the file system. My implementation of my service bean as follows:

public class DeploymentService
	extends ServiceMBeanSupport
		implements DeploymentServiceMBean {

	private static final String
		JBOSS_MAIN_DEPLOYER_SERVICE = "jboss.system:service=MainDeployer";
	private static final String
		JBOSS_DEPLOYMENT_SERVICE = "jboss:service=DeploymentService";

	private MainDeployerMBean mainDeployerService = null;
	private DeploymentServiceMBean jbossDeploymentService = null;

	public void startService() throws Exception {

		try {
			//get proxy for main deployer service bean
			mainDeployerService = getJBossMainDeployer();
		}
		catch (MBeanProxyCreationException e)  {
			e.printStackTrace();
		}

		try {

			//get proxy for deployemnt service bean
			jbossDeploymentService = getJBossDeploymentService();
		}
		catch (MBeanProxyCreationException e)  {
			e.printStackTrace();
		}

		deploy();
	}

	public void stopService() {

	}

	private void deploy()  {

	//hashmap contains properties for the queue template
	HashMap<String, Object> properties = new HashMap<String, Object>();

	//short file name of my queue
	String destination = "myqueue-service.xml";

	//directory name where the queue Velocity template is kept,
	//inside 'dynamic-templates' dir
	String template = "jbossmessaging-queue";

	//property that holds a queue name for the Velocity template
	properties.put("QueueName", "myqueue");

	String resultingFileName = "";

	//create a queue module in a filesystem, at this stage queue
	//is not deployed yet.
	try {
		resultingFileName = jbossDeploymentService
				.createModule(destination, template, properties);
	} catch (Exception e) {
			e.printStackTrace();
	}

	String path = constructPath(destination);

	try {
		//check whether deployment exists for the given
		//module queue in the file system
		if (!mainDeployerService.isDeployed(path)) {

			mainDeployerService.deploy(path);
		}
	} catch (MalformedURLException e) {
		e.printStackTrace();
	}

	}

	//construct an absolute path to the queue module in a filesystem
	//for a given name.
	private String constructPath(String shortName) {
	String path = ServerConfigLocator.locate().getServerHomeDir()
				.getAbsolutePath()
				+ "/"
				+ jbossDeploymentService.getUndeployDir()
				+ "/"
				+ shortName;
		return path;
		}

	//Constructs and returns a proxy for MainDeployerMBean
	private MainDeployerMBean getJBossMainDeployer()
						throws MBeanProxyCreationException
	{
		MBeanServer server = getServer();

		ObjectName serviceName = new ObjectName(JBOSS_MAIN_DEPLOYER_SERVICE);

	//'false' -> dont make the returned proxy implement NotificationEmitter interface
		MainDeployerMBean mainDeployer =
		(MainDeployerMBean) MBeanServerInvocationHandler
					.newProxyInstance(server, serviceName,
						MainDeployerMBean.class, false);

	  return mainDeployer;
	}

	//Constructs and returns a proxy for DeploymentServiceMBean
	private DeploymentServiceMBean getJBossDeploymentService()
						throws MBeanProxyCreationException
	{
		MBeanServer server = getServer();

		ObjectName serviceName = new ObjectName(JBOSS_DEPLOYMENT_SERVICE);

	//'false' -> dont make the returned proxy implement NotificationEmitter interface
		DeploymentServiceMBean deploymentService =
		(DeploymentServiceMBean) MBeanServerInvocationHandler
					.newProxyInstance(server, serviceName,
						DeploymentServiceMBean.class, false);

	  return deploymentService;
	}

}

Two main points that i want to explain here are:
createModule() method of JBoss deployment service and
deploy() of JBoss main deployer.

createModule() - accepts three arguments: resulting file name (in this case is myqueue-service.xml), the directory name where the Velocity template is kept and a HashMap object which contains properties for the template.

JBoss deployment service will use the Velocity template to generate myqueue-service.xml module under dynamic-undeploy directory.

deploy() – accepts a path to the module in the system and deploys the module. In this case the path to the module is:

/opt/mitto/jboss/server/mitto/dynamic-undeploy/myqueue-service.xml

Thats about it :) You can use Velocity templates to deploy queues, message-driven and other types of beans. Basically anything that has XML descriptors.

I really hope I was clear enough in this example, since it is quite con-sized.

Serialize POJO to XML

Today my colleague, Chandana was trying to convert POJO to an XML file. In our company we are working with dom4j library, but unfortunately it does not provide the capabilities to convert a Java object on the fly to an XML.

Off course Chandana could always manually create new Document, root element, sub elements and attributes and that would work fine. But this still does not solves Chandana’s problem where she needed to generate XML on the fly.

After some time doing a research on the Internet she came across this very nice library call XStream. Its a very nice library which allows to serialize objects to XML and back again. It doesn’t require mapping nor modifications to the object itself. They also have a short tutorial which converts a POJO to an XML in few simple steps. Very nice and usefuL