You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Kent Tong <ke...@cpttm.org.mo> on 2008/02/06 02:42:00 UTC

Serialization issue with app scoped beans referenced by session scoped beans

Hi,

Suppose I have a session scoped bean class Bean1 that refers
to an application scoped bean (Bean2) using a managed property:

public class Bean1 implement Serializable {
  private transient Bean2 appBean;
}

The appBean field is marked as transient because as a global object, it is
not
serializable. However, when the Bean1 instance is deserialized, JVM will 
create the bean instance and restore the fields using brute force without
calling 
constructors or involving JSF. It means the appBean field will be null.

Any workaround? This seems to be a design fault in JSF.


-----
--
Kent Tong
Wicket tutorials freely available at http://www.agileskills2.org/EWDW
Axis2 tutorials freely available at http://www.agileskills2.org/DWSAA
-- 
View this message in context: http://www.nabble.com/Serialization-issue-with-app-scoped-beans-referenced-by-session-scoped-beans-tp15303767p15303767.html
Sent from the MyFaces - Users mailing list archive at Nabble.com.


Re: Serialization issue with app scoped beans referenced by session scoped beans

Posted by Kent Tong <ke...@cpttm.org.mo>.

Simon Kitching-4 wrote:
> 
> Of course this does only apply to the fairly rare case of injecting an
> app-scope reference into a session-scoped bean. I cannot see any similar
> problems when injecting session-scope into session-scope, or anything
> into a request-scoped bean.
> 

Thanks for the confirmation. However, I don't understand why you say this
is a rare case. For example, if a session-scoped shopping cart is storing
a list of product IDs. For a page to display the content of the shopping
cart,
it needs not only product IDs, but product names and prices and etc.
To do that, one solution is to inject a Catalog app-scoped bean into the 
shopping cart bean (and thus this case occurs). Another solution (which I
now use) is to create an extra request-scoped bean like CartDisplayHelper 
into which we'll inject both the shopping cart and the Catalog.

Are you saying the second solution is your default? That is, you always have
a Java class specifically created for a specific page? I find it against the
spirit of JSF that there should be no UI logic in Java code.


-----
--
Kent Tong
Wicket tutorials freely available at http://www.agileskills2.org/EWDW
Axis2 tutorials freely available at http://www.agileskills2.org/DWSAA
-- 
View this message in context: http://www.nabble.com/Serialization-issue-with-app-scoped-beans-referenced-by-session-scoped-beans-tp15303767p15328904.html
Sent from the MyFaces - Users mailing list archive at Nabble.com.


Re: Serialization issue with app scoped beans referenced by session scoped beans

Posted by Martin Marinschek <ma...@gmail.com>.
Hi Simon,

Spring's <aop:scoped-proxy/> might help - if it is serializable, and
retrieves the beanFactory on deserialization. However, it doesn't do
it right now; I think - but we discussed with Jürgen once, and maybe
it will be supported in the future.

I doubt the JSF managed-bean facility is sophisticated enough so that
an addition like this makes sense.

regards,

Martin

On Feb 7, 2008 8:13 AM, simon <si...@chello.at> wrote:
>
> On Wed, 2008-02-06 at 19:20 -0800, Kent Tong wrote:
> >
> >
> > Simon Kitching-4 wrote:
> > >
> > > And java's serialization has *always* discarded transient objects on
> > > serialization and marked them as null on deserialization. That's
> > > perfectly normal. There are a number of options here for you, including
> > >   transient Bean2 appBean = new Bean2();
> > > or accessing it only via a getBean2() method that checks whether it is
> > > null and restores it, or implementing custom serialization for Bean1.
> > >
> >
> > Thanks for the reply. My point is that JSF allows injecting an application
> > scoped bean into a session scoped bean. As this is the only way to give
> > the latter access to the former without code pollution, this should be
> > the recommended way suggested by JSF. However, due to the problem
> > raised above, in fact the recommended way is not really working.
>
> That's a fair point.
>
> When a property of a session-scoped bean has been set to an app-scope
> bean via dependency-injection, it is difficult to restore it on
> deserialize. As you say, it really should be transient because you don't
> want to store a copy of the app-scope bean during serialization of an
> http session, and probably don't want a private copy to be created on
> deserialize (but instead be relinked back to the shared app-scope
> instance). It's particularly a problem for distributed sessions.
>
> But there is no way AFAIK to cause the dependency to be reinjected on
> deserialize. The bean can be "looked up", but (a) that is ugly code, and
> (b) breaks the whole point of dependency injection.
>
> Perhaps injection via annotations will work here; the injection process
> could be run against beans after the session is deserialized.
>
> Of course this does only apply to the fairly rare case of injecting an
> app-scope reference into a session-scoped bean. I cannot see any similar
> problems when injecting session-scope into session-scope, or anything
> into a request-scoped bean.
>
> As a hack, I suppose you could write your own
> HttpSessionActivationListener that reinjects stuff based on annotations
> in classes.
>
> I'm not sure what the JSF spec has to say about this issue...
>
> Regards,
> Simon
>
>



-- 

http://www.irian.at

Your JSF powerhouse -
JSF Consulting, Development and
Courses in English and German

Professional Support for Apache MyFaces

Re: Serialization issue with app scoped beans referenced by session scoped beans

Posted by simon <si...@chello.at>.
On Wed, 2008-02-06 at 19:20 -0800, Kent Tong wrote:
> 
> 
> Simon Kitching-4 wrote:
> > 
> > And java's serialization has *always* discarded transient objects on
> > serialization and marked them as null on deserialization. That's
> > perfectly normal. There are a number of options here for you, including
> >   transient Bean2 appBean = new Bean2();
> > or accessing it only via a getBean2() method that checks whether it is
> > null and restores it, or implementing custom serialization for Bean1.
> > 
> 
> Thanks for the reply. My point is that JSF allows injecting an application 
> scoped bean into a session scoped bean. As this is the only way to give 
> the latter access to the former without code pollution, this should be
> the recommended way suggested by JSF. However, due to the problem
> raised above, in fact the recommended way is not really working.

That's a fair point.

When a property of a session-scoped bean has been set to an app-scope
bean via dependency-injection, it is difficult to restore it on
deserialize. As you say, it really should be transient because you don't
want to store a copy of the app-scope bean during serialization of an
http session, and probably don't want a private copy to be created on
deserialize (but instead be relinked back to the shared app-scope
instance). It's particularly a problem for distributed sessions.

But there is no way AFAIK to cause the dependency to be reinjected on
deserialize. The bean can be "looked up", but (a) that is ugly code, and
(b) breaks the whole point of dependency injection.

Perhaps injection via annotations will work here; the injection process
could be run against beans after the session is deserialized.

Of course this does only apply to the fairly rare case of injecting an
app-scope reference into a session-scoped bean. I cannot see any similar
problems when injecting session-scope into session-scope, or anything
into a request-scoped bean.

As a hack, I suppose you could write your own
HttpSessionActivationListener that reinjects stuff based on annotations
in classes.

I'm not sure what the JSF spec has to say about this issue...

Regards,
Simon


Re: Serialization issue with app scoped beans referenced by session scoped beans

Posted by Kent Tong <ke...@cpttm.org.mo>.


Simon Kitching-4 wrote:
> 
> And java's serialization has *always* discarded transient objects on
> serialization and marked them as null on deserialization. That's
> perfectly normal. There are a number of options here for you, including
>   transient Bean2 appBean = new Bean2();
> or accessing it only via a getBean2() method that checks whether it is
> null and restores it, or implementing custom serialization for Bean1.
> 

Thanks for the reply. My point is that JSF allows injecting an application 
scoped bean into a session scoped bean. As this is the only way to give 
the latter access to the former without code pollution, this should be
the recommended way suggested by JSF. However, due to the problem
raised above, in fact the recommended way is not really working.


-----
--
Kent Tong
Wicket tutorials freely available at http://www.agileskills2.org/EWDW
Axis2 tutorials freely available at http://www.agileskills2.org/DWSAA
-- 
View this message in context: http://www.nabble.com/Serialization-issue-with-app-scoped-beans-referenced-by-session-scoped-beans-tp15303767p15326677.html
Sent from the MyFaces - Users mailing list archive at Nabble.com.


Re: Serialization issue with app scoped beans referenced by session scoped beans

Posted by simon <si...@chello.at>.
On Tue, 2008-02-05 at 17:42 -0800, Kent Tong wrote:
> Hi,
> 
> Suppose I have a session scoped bean class Bean1 that refers
> to an application scoped bean (Bean2) using a managed property:
> 
> public class Bean1 implement Serializable {
>   private transient Bean2 appBean;
> }
> 
> The appBean field is marked as transient because as a global object, it is
> not
> serializable. However, when the Bean1 instance is deserialized, JVM will 
> create the bean instance and restore the fields using brute force without
> calling 
> constructors or involving JSF. It means the appBean field will be null.
> 
> Any workaround? This seems to be a design fault in JSF.

This is nothing to do with JSF at all. It's the way http sessions and
serialization work.

HttpSession instances can be serialized/deserialized by the servlet
container under a number of conditions, all listed in the appropriate
specification. If an instance of Bean1 is in the session, it will be
serialized/deserialized too.

And java's serialization has *always* discarded transient objects on
serialization and marked them as null on deserialization. That's
perfectly normal. There are a number of options here for you, including
  transient Bean2 appBean = new Bean2();
or accessing it only via a getBean2() method that checks whether it is
null and restores it, or implementing custom serialization for Bean1.

See a java tutorial on serialization for further information.

Regards, Simon