You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by "Schnack, Malte" <Ma...@qsc.de> on 2007/12/28 18:11:03 UTC

Orchestra: how to access the "real bean" behind the proxies?

In Orchestra, I want to access the "real bean" behind the proxies to
make it available in another context (eg a JBPM variable map). This
seems to be necessary for serialization when invoking an RMI method
using the Orhestra/Spring conversation scoped bean as parameter DTO
object. This is what is happening inside my JBPM process definition.

I already used the ScopedObject method getTargetObject() included in
Spring. This did not resolve to the "real bean" though but to the
CurrentConversationAdvice. When trying to perform the RMI call, my
Glassfish v2 server log shows the following error message:

--- server log ---
[#|2007-12-28T17:48:10.129+0100|WARNING|sun-appserver9.1|javax.enterpris
e.resource.corba.ee._CORBA_.util|_ThreadID=17;_ThreadName=httpSSLWorkerT
hread-8080-1;org.apache.myfaces.orchestra.conversation.CurrentConversati
onAdvice;_RequestID=50deac38-4c13-4e42-b0a7-29460f21969c;|"IOP00100006:
(BAD_PARAM) Class
org.apache.myfaces.orchestra.conversation.CurrentConversationAdvice is
not Serializable"
--- server log ---

Here is the code I am using to propagate the scoped beans to the JBPM
variable map:

--- code ---
[...]
import org.apache.myfaces.orchestra.conversation.Conversation;
import org.apache.myfaces.orchestra.conversation.ConversationManager;
import
org.apache.myfaces.orchestra.conversation.CurrentConversationAdvice;
import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
import org.springframework.aop.scope.ScopedObject;

import com.sun.faces.application.NavigationHandlerImpl;

public class JbpmNavigationHandler extends NavigationHandler {

[...]

			// transfer conversation scoped variables to
pageflow variable map
			Iterator<Conversation> i =
ConversationManager.getInstance()
	
.getCurrentConversationContext().iterateConversations();
			while (i.hasNext()) {
				Conversation conversation = i.next();
				String beanName =
conversation.getName();

				if
(pageflow.getContextInstance().getVariable(beanName) == null) {
					// get the bean (proxy)
					ScopedObject orchestraProxy =
(ScopedObject) FrameworkAdapter
	
.getCurrentInstance().getBean(beanName);

					// dereference spring proxy
					Object bean =
orchestraProxy.getTargetObject();

					logger.debug("resolved proxy ["
+ orchestraProxy
							+ "] to target
[" + bean + "]");

					// ! not the "real bean" but
CurrentConversationAdvice as another proxy (?)
	
pageflow.getContextInstance().setTransientVariable(
							beanName, bean);
				}
			}
--- code ---

Anyone having a hint for me?

Thanks + regards

malte.

AW: AW: Orchestra: how to access the "real bean" behind theproxies?

Posted by "Schnack, Malte" <Ma...@qsc.de>.
Hey Simon, 

> None at the moment, but I'll have a look at the code tomorrow 
> and see if
> I can think of anything else. It certainly would would be good to be
> able to retrieve the real original object, and I don't see 
> why it would
> not be possible.

I just wanted to ask whether you already had a chance to look into this
point again. Help would be highly appreciated.

Regards, 

malte.

-- Have a great new year's eve!

Re: AW: Orchestra: how to access the "real bean" behind the proxies?

Posted by simon <si...@chello.at>.
On Fri, 2007-12-28 at 21:20 +0100, Schnack, Malte wrote:
> Simon, 
> 
> thanks for your feedback.
> 
> > Have you tried this?
> >   Object bean = ...;
> >   while (bean instanceof ScopedObject)
> >     bean = ((ScopedObject) bean).getTargetObject();
> 
> I tried your suggestion. 
> 
> > I think the CurrentConversationAdvice can also be cast to 
> > ScopedObject.
> 
> Unfortunately this does not seem to work out. The object of class
> CurrentConversationAdvice is not instance of ScopedObject. The body of
> the while loop is executed just once.
> 
> Any other ideas?

None at the moment, but I'll have a look at the code tomorrow and see if
I can think of anything else. It certainly would would be good to be
able to retrieve the real original object, and I don't see why it would
not be possible.

Regards, Simon


AW: Orchestra: how to access the "real bean" behind the proxies?

Posted by "Schnack, Malte" <Ma...@qsc.de>.
Simon, 

thanks for your feedback.

> Have you tried this?
>   Object bean = ...;
>   while (bean instanceof ScopedObject)
>     bean = ((ScopedObject) bean).getTargetObject();

I tried your suggestion. 

> I think the CurrentConversationAdvice can also be cast to 
> ScopedObject.

Unfortunately this does not seem to work out. The object of class
CurrentConversationAdvice is not instance of ScopedObject. The body of
the while loop is executed just once.

Any other ideas?

Thanks

malte.

Re: AW: Orchestra: how to access the "real bean" behind the proxies?

Posted by simon <si...@chello.at>.
Hi Malte,

I know this is rather a late response, but I've finally looked into
drilling down from a proxy to a real bean, and it isn't very difficult.

See method _SpringUtils.getRealBean (currently in svn only). It's not a
public method because I don't know if we can provide it for systems
other than Spring. But the code can be called directly (just no promises
about later releases) or can just be copied.

http://svn.apache.org/repos/asf/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/

Regards,
Simon

On Wed, 2008-02-06 at 17:02 +0100, Schnack, Malte wrote:
> Hi,
> 
> to finish this one up, here is a code snipped that does not really resolve the "real bean", but delivers the expected behaviour:
> 
> ---
> 
>   // 0: get the bean (proxy)
>   Object proxy = FrameworkAdapter.getCurrentInstance().getBean(
>       beanName);
> 
>   // 1: un-proxy the Spring Scoped Object
>   while (proxy instanceof ScopedObject) {
>     proxy = ((ScopedObject) proxy).getTargetObject();
>   }
> 
>   // 2: populate a bean instance of the superclass which the CGLIB proxy inherits from
>   Class requiredClass = proxy.getClass().getSuperclass();
> 
>   Object bean = BeanUtils.instantiateClass(requiredClass);
>   BeanUtils.copyProperties(proxy, bean); 
> 
> --- 
> 
> The Variable "bean" now holds an instance of the original class which can then be marshalled for RMI calls.
> 
> My misconception was that I thought, I could get hold of a reference to an instance of my original bean class when obtaining the Spring ScopedObject's target. Instead, what you really get is another CGLIB proxy. I assume that Spring is not aware of this _second_ proxy as this one is crafted by Orchestra. Hence the condition (proxy instanceof ScopedObject) is false.
> 
> Kind regards
> 
> malte.
> 
> 
> > -----Ursprüngliche Nachricht-----
> > Von: simon [mailto:simon.kitching@chello.at] 
> > Gesendet: Freitag, 28. Dezember 2007 19:18
> > An: MyFaces Discussion
> > Betreff: Re: Orchestra: how to access the "real bean" behind 
> > the proxies?
> > 
> > 
> > On Fri, 2007-12-28 at 18:11 +0100, Schnack, Malte wrote:
> > > In Orchestra, I want to access the "real bean" behind the proxies to
> > > make it available in another context (eg a JBPM variable map). This
> > > seems to be necessary for serialization when invoking an RMI method
> > > using the Orhestra/Spring conversation scoped bean as parameter DTO
> > > object. This is what is happening inside my JBPM process definition.
> > > 
> > > I already used the ScopedObject method getTargetObject() included in
> > > Spring. This did not resolve to the "real bean" though but to the
> > > CurrentConversationAdvice. When trying to perform the RMI call, my
> > > Glassfish v2 server log shows the following error message:
> > 
> > I think the CurrentConversationAdvice can also be cast to 
> > ScopedObject.
> > Have you tried this?
> >   Object bean = ...;
> >   while (bean instanceof ScopedObject)
> >     bean = ((ScopedObject) bean).getTargetObject();
> > 
> > Regards,
> > 
> > Simon
> > 
> > 


AW: Orchestra: how to access the "real bean" behind the proxies?

Posted by "Schnack, Malte" <Ma...@qsc.de>.
Hi,

to finish this one up, here is a code snipped that does not really resolve the "real bean", but delivers the expected behaviour:

---

  // 0: get the bean (proxy)
  Object proxy = FrameworkAdapter.getCurrentInstance().getBean(
      beanName);

  // 1: un-proxy the Spring Scoped Object
  while (proxy instanceof ScopedObject) {
    proxy = ((ScopedObject) proxy).getTargetObject();
  }

  // 2: populate a bean instance of the superclass which the CGLIB proxy inherits from
  Class requiredClass = proxy.getClass().getSuperclass();

  Object bean = BeanUtils.instantiateClass(requiredClass);
  BeanUtils.copyProperties(proxy, bean); 

--- 

The Variable "bean" now holds an instance of the original class which can then be marshalled for RMI calls.

My misconception was that I thought, I could get hold of a reference to an instance of my original bean class when obtaining the Spring ScopedObject's target. Instead, what you really get is another CGLIB proxy. I assume that Spring is not aware of this _second_ proxy as this one is crafted by Orchestra. Hence the condition (proxy instanceof ScopedObject) is false.

Kind regards

malte.


> -----Ursprüngliche Nachricht-----
> Von: simon [mailto:simon.kitching@chello.at] 
> Gesendet: Freitag, 28. Dezember 2007 19:18
> An: MyFaces Discussion
> Betreff: Re: Orchestra: how to access the "real bean" behind 
> the proxies?
> 
> 
> On Fri, 2007-12-28 at 18:11 +0100, Schnack, Malte wrote:
> > In Orchestra, I want to access the "real bean" behind the proxies to
> > make it available in another context (eg a JBPM variable map). This
> > seems to be necessary for serialization when invoking an RMI method
> > using the Orhestra/Spring conversation scoped bean as parameter DTO
> > object. This is what is happening inside my JBPM process definition.
> > 
> > I already used the ScopedObject method getTargetObject() included in
> > Spring. This did not resolve to the "real bean" though but to the
> > CurrentConversationAdvice. When trying to perform the RMI call, my
> > Glassfish v2 server log shows the following error message:
> 
> I think the CurrentConversationAdvice can also be cast to 
> ScopedObject.
> Have you tried this?
>   Object bean = ...;
>   while (bean instanceof ScopedObject)
>     bean = ((ScopedObject) bean).getTargetObject();
> 
> Regards,
> 
> Simon
> 
> 

Re: Orchestra: how to access the "real bean" behind the proxies?

Posted by simon <si...@chello.at>.
On Fri, 2007-12-28 at 18:11 +0100, Schnack, Malte wrote:
> In Orchestra, I want to access the "real bean" behind the proxies to
> make it available in another context (eg a JBPM variable map). This
> seems to be necessary for serialization when invoking an RMI method
> using the Orhestra/Spring conversation scoped bean as parameter DTO
> object. This is what is happening inside my JBPM process definition.
> 
> I already used the ScopedObject method getTargetObject() included in
> Spring. This did not resolve to the "real bean" though but to the
> CurrentConversationAdvice. When trying to perform the RMI call, my
> Glassfish v2 server log shows the following error message:

I think the CurrentConversationAdvice can also be cast to ScopedObject.
Have you tried this?
  Object bean = ...;
  while (bean instanceof ScopedObject)
    bean = ((ScopedObject) bean).getTargetObject();

Regards,

Simon