0

I'm maintaining some code that has the following method:

private void loadNotifications() 
{
    final Map notifications = (Map) getManagedBean("notifications");

    ...
}

The map is being added to the session and is not serializable, so reconstructing it with a session manager throws an error. The item itself is some legacy code that is a JSF managed bean. If the Map was at the class level, e.g.

public class Notifications 
{
    final Map notifications;
}

I'd have two options - have the class implement serializable (not desirable here as the parent class has many fields I want in the session, and the action is used a lot) or simply use the transient modifier on the field I want to exclude. However, I can't do that from within the method as the transient modifier is not allowed.

Please let me know if any more detail is required to complete the example - I was mostly wondering if there is a general approach to making transient method variables like I can with class variables.

EDIT:

I've been accused of proposing a solution as the problem. So first, some background: My goal is to store my application's sessions in a memcached-backed Elasticache for high availability purposes. I have set up a session manager to this end, and when I run my application, I get the following error:

Jul 05, 2016 10:19:09 AM   de.javakaffee.web.msm.JavaSerializationTranscoder writeAttributes
WARNING: Cannot serialize session attribute notifications for    session A79414F801E44C2B8207CEF3532FA80A
java.io.NotSerializableException: com.google.gson.JsonArray
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at java.util.HashMap.internalWriteEntries(HashMap.java:1777)
at java.util.HashMap.writeObject(HashMap.java:1354)
at sun.reflect.GeneratedMethodAccessor141.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1028)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at de.javakaffee.web.msm.JavaSerializationTranscoder.writeAttributes(JavaSerializationTranscoder.java:138)
at de.javakaffee.web.msm.JavaSerializationTranscoder.serializeAttributes(JavaSerializationTranscoder.java:99)
at de.javakaffee.web.msm.TranscoderService.serializeAttributes(TranscoderService.java:154)
at de.javakaffee.web.msm.BackupSessionTask.serializeAttributes(BackupSessionTask.java:180)
at de.javakaffee.web.msm.BackupSessionTask.call(BackupSessionTask.java:110)
at de.javakaffee.web.msm.BackupSessionTask.call(BackupSessionTask.java:51)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

The problem as I have described is thus fairly evident - there is data in my session that cannot be serialized. I have solved similar problems before by making a class implement Serializable or making some fields transient. However, since this case has a method-scope and because it is impractical to make its parent class serializable, my original question was how one might avoid serializing a variable within a method given my context. If someone can propose another solution to my root problem of not being able to store my session/run my app as I intend, then please do.

Rome_Leader
  • 2,518
  • 9
  • 42
  • 73
  • I don't see how you would solve that on method scope; besides maybe doing some try/catch; expecting the catch cause and doing something useful there. – GhostCat Jul 06 '16 at 11:40
  • It seems like you're being rude for the sake of it. I've described the problem as I see it. If you have a productive suggestion or wish to clarify my confusion, I do welcome it. If you'd like any more details, I can try to provide them. – Rome_Leader Jul 06 '16 at 12:58
  • I'm entirely aware of the perils of posing a solution as the problem. However, I don't think the error message offers much room for interpretation. I have included it above, but I feel it muddies what was intended to be a general question about the preferred approach to mark method data as transient. – Rome_Leader Jul 06 '16 at 17:13
  • 1
    The problem is not the local variable. The problem is the managed bean class itself which appears to implement/extend map and has some non-serializable `JsonArray` instance as an entry. Fix it over there as per instructions in the duplicate. The `loadNotifications()` method can't sensibly do that as local variables are never serialized. – BalusC Jul 07 '16 at 11:50
  • Thanks for the helpful link, but I don't know if I can quite solve my problem in the same way. The accepted answer simply suggests to have the class name in the exception implement serializable - in my error above, that's the Google library class com.google.gson.JsonArray as you mention which I obviously can't change. Maybe a wrapper of some sort is in order? – Rome_Leader Jul 07 '16 at 11:56
  • Yep, see also "Mark unserializable fields transient" section of accepted answer. As a hint for future comment replies, if more than one person has posted a comment on your post, use `@nickname` to notify the person of interest, otherwise no one will get notified. I only saw your reply when I come back here during reviewing my previously posted comments. – BalusC Jul 11 '16 at 09:50

0 Answers0