GWT + Hibernate + Dispatch

When creating a portal, very often the main function of BackEnd is working with the database. As a rule, now no one uses the usual and not very convenient for writing Statements, and in place of this they use ORM frameworks. In the case of GWT, this framework most likely becomes Hibernate, since we have Java on the server. It was not my first thought that it would be extremely convenient and simple to transfer not individual data but the entire POJO (persistent objects) used by Hibernate. So I created my service, returning to the client part of POJO. POJO inherited from Serializable. I launch the application and get this exception:

Caused by: com.google.gwt.user.client.rpc.SerializationException: Type 'org.hibernate.collection.PersistentSet' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.
at com.google.gwt.user.server.rpc.impl.StandardSerializationPolicy.validateSerialize(StandardSerializationPolicy.java:83)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:591


It’s not immediately clear what went wrong. The fact is that as soon as an object becomes persistent, a series of changes are necessary in it, necessary for Hibernate to work. For example, the regular Set changes to a PersistentSet. Because of this, the browser can no longer deserialize the object sent to it, under any circumstances.

Integration Methods

As I already said, I am not the first who wanted to transfer POJO to the client side, and as a result, not the first who faced a similar problem. On the Internet, you can find three main ways to solve this problem and integrate Hibernate with GWT.
• DTO (Data Transfer Objects) - you can create your own objects for transferring data to the client part of the application that are not persistent, but otherwise contain all the same fields as in the POJO you are using.
• Using the Dozer library to map objects - This library automatically copies data from one object to another. For its correct operation, Objects must contain the same fields and getters and setters named in accordance with the JavaBean notation.
• Using the Gilead library also known as hibernate4gwt.
The first option is quite trivial, and I will not consider it, as well as the second, which is just a little more advanced first. If you are interested in the second option, you can find all the necessary information about the library on the official site dozer.sourceforge.net

Gilead

Much more interesting is the last option, which I will talk about now. Glead is an open library that provides the ability to freely transfer POJO between the client and server parts of the application. When using this library on a server, a layer called PersistentBeanManager appears between the Java server and the client. When transmitting an object from the server to the client, PBM automatically clones the POJO into a similar client object, while ignoring all LazyInitiaslization and replacing the fields that are not yet initialized with NULL. At the same time storing POJO in memory. On the return run, PBM blinks the client object with the POJO stored in it and transfers it to the POJO server with the already updated data.
To use this incredibly convenient miracle, you need to add a project library. Connect the required module to gwt.xml, inherit all POJO LightEntity, and use the servlet instead of RemoteServiceServlet PersistantRemoteService. Perhaps it would be worthwhile to simply describe this process and end this article, but as you see in the title of the article there is the word Dispatch. The fact is that many people use the Dispatch programming pattern with the gwt-dispatch library based on dependency injection using the Guice library to reuse code. When using such a library, there is no service class in your project. You use the standard GuiceStandardDispatchServlet service, which is wired inside the gwt-dispatch library. In order to get around this, I slightly rebuilt this library.

Gilead + Dispatch

First you need to rebuild the gwt-dispatch library. For this, we use some client of mercury and take the resources from the repository. hg clone code.google.com/p/gwt-dispatch
We create a project in the IDE in which it is more convenient for you where we put all this. I am using Eclipse. Further, to make the project work, I added the following libraries to
.classpath • gilead-core-1.3.2.1839.jar
• gliead-hibernate-1.3.2.1839.jar
• glead4gwt-1.3.2.1839.jar
• gin-1.5-post-gwt-2.2 .jar
• guice-3.0.jar
• hibernate.jar
• org.springframework.beans-3.1.2.RELEASE.jar
• org.springframework.context-3.1.2.RELEASE.jar
• org.springframework.web-3.1.2 .RELEASE.jar
We open the net.customware.gwt.dispatch.server.standard.AbstractStandardDispatchServlet class and make several changes to it for our library to work correctly:
public abstract class AbstractStandardDispatchServlet extends
		PersistentRemoteService implements StandardDispatchService {
	public AbstractStandardDispatchServlet() {
		HibernateUtil hibernateUtil = new HibernateUtil();
		SessionFactory sf;
		Configuration conf = new Configuration();
		conf.configure();
		conf.getProperties();
		sf = conf.buildSessionFactory();
		hibernateUtil.setSessionFactory(sf);
		PersistentBeanManager persistentBeanManager = new PersistentBeanManager();
		persistentBeanManager.setPersistenceUtil(hibernateUtil);
		StatelessProxyStore sps = new StatelessProxyStore();
		sps.setProxySerializer(new GwtProxySerialization());
		persistentBeanManager.setProxyStore(sps);
		setBeanManager(persistentBeanManager);
	}
	public  R execute(Action action)
			throws DispatchException {
		try {
			Dispatch dispatch = getDispatch();
			if (dispatch == null)
				throw new ServiceException("No dispatch found for servlet '"
						+ getServletName()
						+ "' . Please verify your server-side configuration.");
			return dispatch.execute(action);
		} catch (RuntimeException e) {
			log("Exception while executing " + action.getClass().getName()
					+ ": " + e.getMessage(), e);
			throw new ServiceException(e);
		}
	}
	/**
	 * 
	 * @return The Dispatch instance.
	 */
	protected abstract Dispatch getDispatch();
}

After all the changes have been made, we can safely build the library and add it to the project (or you can simply replace the .class file in the old one). It is also necessary to add the following libraries to the project
• beanlib-5.0.5.jar
• beanlib-hibernate-5.0.5.jar
• com.springsource.net.sf.cglib-2.2.0.jar

We include gilead in gwt.xml so that the client side knew about our LightEntity

And inherited by all POJO LightEntity as shown below
@Entity
@Table(name = "CARD")
public class Card extends LightEntity implements Serializable {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "CARDID", columnDefinition = "BIGINT NOT NULL AUTO_INCREMENT")
	private long cardId;
	@Column(name = "CARDNUMBER")
	private String cardNumber;
	@ManyToOne
	@JoinColumn(name = "USERID", insertable = false, updatable = false, nullable = false)
	private User user;
	@Column(name = "ACTIVATED")
	private Integer activated;
	public Long getCardId() {
		return cardId;
	}
	public void setCardId(Long cardId) {
		this.cardId = cardId;
	}
	public String getCardNumber() {
		return cardNumber;
	}
	public void setCardNumber(String cardNumber) {
		this.cardNumber = cardNumber;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	public Integer getActivated() {
		return activated;
	}
	public void setActivated(Integer activated) {
		this.activated = activated;
	}
}

Well, that's all. Now you can safely transfer your persistent objects between the server and client parts of the GWT application while continuing to use Dispatch.

Also popular now: