Salut à tous,

J'utilise SWF 2.4.1 et Hib 4.3.6 dans mon application.

La session hibernate étant liée à la session HTTP, celle-ci est sérialisée/désérialisée à chaque requête.

Dans mon flow à un moment, j'ai trois nouvelles entités avec A qui référence B et B qui référence C.

Ces objets sont mis dans la map entitySnapshotsByKey de la classe org.hibernate.engine.internal.StatefulPersistenceContext avec la valeur org.hibernate.engine.spi.PersistenceContext.NO_ROW (de type ObjectMarker)

Si persist() est appelé pour une nouvelle entité, une vérification dans la cache est faite pour les entités associées via la méthode org.hibernate.engine.internal.StatefulPersistenceContext.getDatabaseSnapshot(Serializable, EntityPersister).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
 
public Object[] getDatabaseSnapshot(Serializable id, EntityPersister persister) throws HibernateException {
		final EntityKey key = session.generateEntityKey( id, persister );
		final Object cached = entitySnapshotsByKey.get( key );
		if ( cached != null ) {
			return cached == NO_ROW ? null : (Object[]) cached;
		}
		else {
			final Object[] snapshot = persister.getDatabaseSnapshot( id, session );
			entitySnapshotsByKey.put( key, snapshot == null ? NO_ROW : snapshot );
			return snapshot;
		}
	}
Le premier passage dans cette méthode va mettre les nouveaux objets dans entitySnapshotsByKey avec la valeur NO_ROW.

Une sérialisation/désérialisation a ensuite lieu lors du passage à l'écran suivant du flow.

Lors du persist() de la nouvelle entité suivante un call à getDatabaseSnapshot est de nouveau effectué et cette fois-ci les nouvelles entités étant disponibles, cached aura la valeur NO_ROW.

Le problème est là, suite à la désérialisation ce n'est plus la même référence que le NO_ROW de PersistenceContext!

Donc la ligne suivant "return cached == NO_ROW ? null : (Object[]) cached;" va essayer de caster l'ObjectMarker en Object[].

Donnant l'erreur suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 
java.lang.ClassCastException: org.hibernate.internal.util.MarkerObject cannot be cast to [Ljava.lang.Object;
at org.hibernate.engine.internal.StatefulPersistenceContext.getDatabaseSnapshot(StatefulPersistenceContext.java:313)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:255)
at org.hibernate.engine.internal.ForeignKeys$Nullifier.isNullifiable(ForeignKeys.java:177)
at org.hibernate.engine.internal.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:105)
at org.hibernate.engine.internal.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:81)
at org.hibernate.action.internal.AbstractEntityInsertAction.nullifyTransientReferencesIfNotAlready(AbstractEntityInsertAction.java:130)
at org.hibernate.action.internal.AbstractEntityInsertAction.makeEntityManaged(AbstractEntityInsertAction.java:141)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:201)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:179)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:166)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:332)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:137)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at core.dao.generic.AbstractHibernateDao.persist(AbstractHibernateDao.java:45)
at web.flow.controller.DenoFlowController.saveDenomination(DenoFlowController.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:63)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:95)
at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:44)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:258)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:84)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:105)
at org.springframework.binding.expression.spel.SpringELExpression.getValue(SpringELExpression.java:84)
at org.springframework.webflow.action.EvaluateAction.doExecute(EvaluateAction.java:75)
at org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:188)
at org.springframework.webflow.execution.AnnotatedAction.execute(AnnotatedAction.java:145)
at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51)
at org.springframework.webflow.engine.support.ActionTransitionCriteria.test(ActionTransitionCriteria.java:82)
at org.springframework.webflow.engine.support.TransitionCriteriaChain.test(TransitionCriteriaChain.java:68)
at org.springframework.webflow.engine.Transition.canExecute(Transition.java:196)
at org.springframework.webflow.engine.Transition.execute(Transition.java:212)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)
at org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)
at org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)
at org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)
at org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)
at org.springframework.webflow.engine.ViewState.handleEvent(ViewState.java:231)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:195)
at org.springframework.webflow.engine.Flow.resume(Flow.java:537)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:228)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Ma question est donc la suivant, est-il possible d'empêcher la sérialisation de la session hibernate dans la config SWF?

Est-ce un problème dans l'implémentation de la méthode org.hibernate.engine.internal.StatefulPersistenceContext.deserialize(ObjectInputStream, SessionImplementor) line 1530 qui ne gère pas correctement les désérialisation des ObjectMarker ou est-ce la comparaison de référence qui est une erreur? (pas de equals() disponible dans ObjectMarker)


Merci pour votre aide.