How to use LoadableDetachableModel in Wicket, Spring, a Hibernate-based web application?

I am developing a web application based on Hibernate, Spring and Wicket.

So far I have implemented business objects and retention level. The transaction is controlled by the transactional interceptor of the Spring structure. Therefore, each method of the DAO classes is encapsulated in a transaction. Implementing this with the unit test was straightforward.

Now I come to the part of the web application where I also use Spring for dependency injection. Along with the @SpringBean annotations of the Wicket framework, I introduce DAO into the Wicket components. But since I'm fairly new to Wicket, I got a little stuck using the right model for my business objects when the Wicket components pass them.

I tried LoadableDetachableModel but ran into some problems. I got one page for creating a new or editing an existing business object depending on the input parameters of the page. If there is an identifier in the parameters, then the corresponding business object must be loaded from the database. When there are no parameters, you need to create a new business object. This part should have been edited, but you need to create a new object, and I will fill in the web form and click "Save", I get a NullPointerException. After some debugging, I found that the LoadableDetachableModel could not return an instance of the business object, since the overridden load () method could not load the database object form, since it had not yet been saved and therefore had no identifier.

So now I am wondering how to solve this problem. Is LoadableDetachableModel the right choice? Is it desirable to divide the form into two interdependent forms, and each form uses a different model. So, only the edit page / form uses the LoadableDetachableModel?

+4
source share
2 answers

There is a good explanation of this and some related questions by Igor Weinberg on the Wicket In Action blog .

The last bit on this page addresses this issue, mainly not using the LoadableDetachableModel , but implementing the AbstractEntityModel , which allows more complete control.

+2
source

Wicket 6.x Reference Documentation> 11 Calibration Models and Forms> 11.6 Removable models describe this as follows:

Now, as an example of the possible use of the LoadableDetachableModel , we will build a model designed to work with entities controlled through JPA. To understand the following code, knowledge of JPA basic knowledge is necessary even if we do not go into the details of this standard.

The following model is provided as an example only and is not intended for use in a production environment. Important aspects since transaction management is not taken into account, and you must rework the code before using it.

 public class JpaLoadableModel<T> extends LoadableDetachableModel<T> { private EntityManagerFactory entityManagerFactory; private Class<T> entityClass; private Serializable identifier; private List<Object> constructorParams; public JpaLoadableModel(EntityManagerFactory entityManagerFactory, T entity) { super(); PersistenceUnitUtil util = entityManagerFactory.getPersistenceUnitUtil(); this.entityManagerFactory = entityManagerFactory; this.entityClass = (Class<T>) entity.getClass(); this.identifier = (Serializable) util.getIdentifier(entity); setObject(entity); } @Override protected T load() { T entity = null; if(identifier != null) { EntityManager entityManager = entityManagerFactory.createEntityManager(); entity = entityManager.find(entityClass, identifier); } return entity; } @Override protected void onDetach() { super.onDetach(); T entity = getObject(); PersistenceUnitUtil persistenceUtil = entityManagerFactory.getPersistenceUnitUtil(); if(entity == null) return; identifier = (Serializable) persistenceUtil.getIdentifier(entity); } } 

The model constructor takes two parameters as input: the JPA javax.persistence.EntityManagerFactory interface for managing JPA objects and which should be processed by this model. Inside its constructor, the model stores the class of the object and its identifier (which may be null if the object has not yet been saved). These two are required to obtain the object later and the loading method is used.

onDetach is responsible for updating the object identifier before the breakaway takes place. An identifier can change the first time an object is saved (JPA generates a new identifier and assigns it to entities). Please note that this model is not responsible for saving any changes that have occurred to the object of the object before disconnecting it. If we do not want to lose these changes, we must explicitly save the object before disconnecting the phase.

Since the model of this example contains a reference to EntityManagerFactory , the implementation used must be Serializable .

0
source

All Articles