[
http://jira.jboss.com/jira/browse/JBSEAM-2221?page=comments#action_12392323 ]
Wolfgang Schwendt commented on JBSEAM-2221:
-------------------------------------------
Correction of some typos:
Now let's get back to the question how a proxy rather than directly the Java-this
pointer can be passed to another component. My idea was first that a component looks up
its own component name via the MethodContext and then retrieves a proxy to itself via
Component.getInstance(componentName, false). However, this solution is not possible,
because during the time Component executes, it is enclosed by the MethodContextInterceptor
which provides that the Component can only retrieve an "unproxied" reference to
itself. Therefore I chose the following alternative approach: the Component simply looks
up its own name and then passes its component name as a String to the other component.
When the second component wants to invoke the first component at a later point of time, it
retrieves a proxy to the first component via an ordinary call of Component.getInstance().
If the latter approach is chosen, it is possible to modify the
org.jboss.seam.framework.Query and org.jboss.seam.trinidad.EntityCollectionModel in such a
way, that the Query component can be conversation-scoped and nevertheless the DataModel
(EntityCollectionModel) gets not affected/broken by the
ManagedEntityIdentityInterceptor. The idea is that the DataModel does not directly contain
any Entities, but Entities are only managed by the Query component. In order to retrieve
data for a row, the DataModel invokes the Query component, but does this through a proxy
rather than the Java-this-pointer. Therefore, the ManagedEntityIdentityInterceptor comes
into play and first restores the internal state of the Query component. This approach
however requires a modification to ManagedEntityIdentityInterceptor that it becomes more
selective and doesn't process any DataModel fields the value of which are an instance
of EntityCollectionModel. (the latter is a special DataModel implementation which
doesn't store any Entities, so it doesn't have to be processed by the
ManagedEntityIdentityInterceptor).
Introduce way to retrieve proxy object of a Seam JavaBean Component
-------------------------------------------------------------------
Key: JBSEAM-2221
URL:
http://jira.jboss.com/jira/browse/JBSEAM-2221
Project: JBoss Seam
Issue Type: Feature Request
Reporter: Wolfgang Schwendt
The EJB programming model requires that a Session Bean never passes a
"this"-pointer to other client objects. Instead,
javax.ejb.SessionContext provides a method getBusinessObject(). If a SessionBean wants to
pass a reference pointing to itself to other clients, it first has to retrieve its own EJB
object reference by calling SessionContext.getBusinessObject() which it then can pass to
other beans. This reference returned by javax.ejb.SessionContext.getBusinessObject() is
the equivalent to Java's this pointer.
With respect to Seam's interceptor framework, such a feature is missing as far as
normal JavaBean components are concerned. It leads to subtle programming errors:
Consider the implementation of org.jboss.seam.framework.Query. getDataModel():
/**
* Wrap the result set in a JSF {@link DataModel}
*
* Delegates to {@link DataModels#getDataModel(Query)}
*
*/
@Transactional
public DataModel getDataModel()
{
if (dataModel==null)
{
dataModel = DataModels.instance().getDataModel(this);
}
return dataModel;
}
This method method passes a "this"-reference to the
org.jboss.seam.faces.dataModels Seam-component.
But this can lead to a behavior not expected by the programmer. If the
(Entity)Query-component gets instantiated as a conversation-scoped component, Seam wraps
the ManagedEntityIdentityInterceptor around this Query component.
After each method invocation intercepted by the ManagedEntityIdentityInterceptor, the
ManagedEntityIdentityInterceptor saves wrappers for all contained Entity references in the
conversation context and sets the corresponding reference fields in the Query component to
null.
Now, consider again above implementation of Query.getDataModel(). Because a
"this" pointer is passed to the dataModels-component, any calls conducted by the
datamodel-component via this reference won't (!) be routed through the
ManagedEntityIdentity interceptor. Hence, when the datamodel-component calls the
Query-component via the Java-this pointer it received previously, the
ManagedEntityIdentity won't be invoked and in turn the Entity reference fields in the
Query-component won't be restored.
This leads to a bug as described in JBSEAM-1814. In order to fix that bug, we would have
to change the implementation of Query. getDataModel(). Rather than passing the Java-this
pointer to the dataModels component, the correct implementation would be as follows. The
Query component would first have to retrieve a reference to its own proxy object, which it
then could pass to the dataModels component.
Summary: For JavaBean Seam components we need a feature similar to
SessionContext.getBusinessObject(), to enable a JavaBean Seam component to pass a proxy
reference to itself to other Seam components instead of passing directly the Java-this
pointer.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira