[jbossseam-issues] [JBoss JIRA] Commented: (JBSEAM-2221) Introduce way to retrieve proxy object of a Seam JavaBean Component

Wolfgang Schwendt (JIRA) jira-events at lists.jboss.org
Sun Dec 16 08:51:54 EST 2007


    [ http://jira.jboss.com/jira/browse/JBSEAM-2221?page=comments#action_12392322 ] 
            
Wolfgang Schwendt commented on JBSEAM-2221:
-------------------------------------------

I investigated above issue again and have to add the following for the sake of completion.   First of all,   my above argument cited as example why passing of a proxy rather than the Java-this-pointer would be useful was not good.  Even if the getDataModel() method of org.jboss.seam.framework.Query passed a proxy to org.jboss.seam.faces.DataModels.getDataModel(Object value), it would not solve the problem that occurs when the Query component is defined with conversation scope and thus a ManagedEntityIdentityInterceptor is attached to it.  In the cited example, DataModels.getDataModel(Object value) doesn't do much, it just calls the Query component back with query.getResultList() and then wraps this resultList.   Afterwards the constructed DataModel nevers call the Query component back.    And the only callback happens while the method Query.getDataModel() encloses this callback on the execution stack, so during the time this callback is executed no field in the Query component is cleared by the ManagedEntityIdentityInterceptor.   However, the problem with the ManagedEntityIdentityInterceptor and a conversation-scoped Query component  is that once Query.getDataModel() completes, the ManagedEntityIdentityInterceptor nulls the list encapsulated by the DataModel stored in the field Query.dataModel.  And because Query.getDataModel() returns a reference to the DataModel stored in the field Query.dataModel, the side-effect of ManagedEntityIdentityInterceptor.entityRefsToIds() is that the list wrapped by the DataModel, which is returned by Query.getDataModel(),  gets cleared as well.
So the problem in this case is that Query.getDataModel()  return an alias to internal state which gets cleared by the  ManagedEntityIdentityInterceptor once Query.getDataModel()  completes.


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 String to the other component.     When the second component wants to invoke the first component at a later point, it retrieves a proxy to the first component via an ordinary call to 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 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 row data, 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 restore 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 is an instance of EntityCollectionModel.    (the latter 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

       




More information about the seam-issues mailing list