⬆️ ⬇️

GWT + Hibernate + Dispatch

When creating a portal, very often the main function of BackEnd is to work with the database. As a rule, now no one uses the usual and not very convenient for writing Statement'y, and in place of this use ORM frameworks. In the case of GWT, this framework is likely to become Hibernate, since we have Java on the server. I was not the first to think 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 the POJO. POJO is inherited from Serializable. I run the application and get the following 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 was not immediately clear what went wrong. The fact is that as soon as an object becomes persistent, a number of changes occur in it that are necessary for Hibernate to work. For example, the usual Set is changed to PersistentSet. Because of this, the browser can no longer deserialize the object sent to it, under any circumstances.

')

Integration Ways


As I have already said, I am not the first who wanted to transfer the POJO to the client side, and as a result, it was 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 objects to transfer data to the client side of the application that are not persistent, but otherwise contain all the same fields as in the POJOs you use.

• Using the Dozer library for mapping objects - This library automatically copies data from one object to another. For it to work correctly, Objects must contain the same fields and getters and setters named according to 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 website dozer.sourceforge.net



Gilead


Much more interesting is the last option, which I will now tell. Glead is an open library that provides the ability to freely transfer POJOs between the client and server parts of an application. When using this library, a layer called PersistentBeanManager appears on the server between the Java server and the client. When an object is transferred from the server to the client, the PBM automatically clones the POJO into a similar client object, while ignoring all LazyInitiaslization and replacing the fields that have not yet been initialized with NULL. At the same time keeping the POJO in memory. On the reverse PBM, the client object is stored with the POJO stored in it and sends the POJO with already updated data to the server.

To use this incredibly convenient miracle you need to add a library project. Connect the required module to gwt.xml, examine all POJO LightEntity, and use the servlet instead of the RemoteServiceServlet PersistantRemoteService. Perhaps it would be worthwhile to simply describe this process and end with this article, but as you can see in the title of the article there is the word Dispatch. The fact is that a lot of 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 in your project there is no service class. You use the standard GuiceStandardDispatchServlet service, which is sewn 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 mercury client and take the surases 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 all this is and we push. I use Eclipse. Further that the project would gather 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

Open the net.customware.gwt.dispatch.server.standard.AbstractStandardDispatchServlet class and make several changes to it in order 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 extends Result> R execute(Action<R> 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 in gwt.xml gilead so that the client side knows about our LightEntity

 <inherits name="net.sf.gilead.Gilead4Gwt" /> 


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.

Source: https://habr.com/ru/post/154321/



All Articles