2016-07-13 20 views
0

Oft arbeite ich an Java EE-Anwendung. Heute stehe ich vor einem Problem: Sammlungen im Servlet-Kontext serialisieren. In meinem Fall enthält meine App einen Servlet Context Listener und viele Servlets.Servlet Context, Collections und Serialization

  • Der Context-Listener lädt eine ConcurrentHashMap, die mehrere Produktlisten bei der Initialisierung enthält, und einen Taskplaner, um diese Liste zu aktualisieren.
  • Die Servlets sollen basierend auf den vom Benutzer bereitgestellten Parametern auf die richtige Liste zugreifen.

Hier ist der Code meines contextInitialized Zuhörer:

public void contextInitialized(ServletContextEvent event) { 
    app = event.getServletContext(); 
    myMap = new ConcurrentHashMap<String, Catalog>(); 
    myMap.put("FR", new Catalog()); 
    myMap.put("UK", new Catalog()); 
    app.setAttribute("catalogue", myMap); 
    scheduler = Executors.newSingleThreadScheduledExecutor(); 
    scheduler.scheduleAtFixedRate(new AutomateRefresh(), 0, 60, TimeUnit.MINUTES); 
} 

Um mein Problem zu zeigen, habe ich ein Servlet, die alles zeigen, die einen boolean ist oder eine ConcurrentHashMap in Zusammenhang ich bin nicht überrascht, diese Art von Ergebnissen zu finden:

javax.servlet.context.tempdir is equal to... 
Working is equal to... true 
org.apache.catalina.resources is equal to... 
org.apache.tomcat.InstanceManager is equal to... 
org.apache.catalina.jsp_classpath is equal to... 
javax.websocket.server.ServerContainer is equal to... 
org.apache.jasper.compiler.TldCache is equal to... 
catalogue is equal to... 
org.apache.tomcat.JarScanner is equal to... 

Wie Sie, meine zwei benutzerdefinierten Schlüssel (die boolean Arbeiten und der ConcurrentHashMap Katalog) existieren sehen. Aber Katalog ist leer, wenn nicht innerhalb des Listeners zugegriffen wird. I

festgestellt, dass:

Die Serialisierung Form java.util.HashMap nicht die Eimer selbst nicht serialisiert, und der Hash-Code ist nicht Bestandteil des beibehaltenen Zustand.

Quelle: Serializing and deserializing a map with key as string

Bei vielen Projekten ein serializable und Thread-sichere Sammlung ist nützlich. Ich bin wahrscheinlich nicht der Einzige, der danach sucht (siehe die Menge des Themas zum Servlet-Kontext).

ConcurrentHashMap ist Thread-sicher, aber ich kann meine Daten in anderen Servlet (in der gleichen App) nicht abrufen. Gibt es eine Implementierung von Collection, die Thread-sicher und serialisierbar ist (aufgrund der WebLogic-Serverrichtlinie)? Oder verwende ich es falsch?

EDIT: Code von "Display Kontext Servlet"

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ 
    System.out.println("List of all values in the context:"); 
    Enumeration<?> e = getServletContext().getAttributeNames(); 
    while (e.hasMoreElements()) 
    { 
     String name = (String) e.nextElement(); 
     System.out.print("\n" + name + " is equal to... "); 

     // Get the value of the attribute 
     Object value = this.getServletContext().getAttribute(name); 

     if (value instanceof ConcurrentHashMap) { 
      ConcurrentHashMap<String, Catalog> map = (ConcurrentHashMap<String, Catalog>) value; 

      Iterator<Entry<String, Catalog>> it = map.entrySet().iterator(); 

      while (it.hasNext()) { 
       ConcurrentHashMap.Entry<String, Catalog> entry = (ConcurrentHashMap.Entry<String, Catalog>)it.next(); 
       System.out.print("\t" + entry.getKey() + "=" + entry.getValue()); 
      } 
     } else if (value instanceof Boolean) { 
      System.out.print((Boolean)value); 
     } 
    } 
} 

EDIT2: Wie BalusC vorgeschlagen, die HashMap vielleicht null (ein Anfängerfehler?).

Hier der Aufgabencode. Die Aufgabe befindet sich im Listener. Der Listener initialisiert die HashMap mit einem neuen leeren Objekt. Die Aufgabe aktualisiert die Objekte beim Start der webapp und dann jede Stunde.

Wenn die Aufgabe ausgelöst wurde, aktualisiert die Aufgabe für jeden im Kontext gespeicherten Katalog die von ihnen gespeicherten Daten. Es zeigt auch Daten in der Konsole an.

Ergebnisse:

Refresh Catalog for UK with DB 
UK = Catalog [list size is : 0 valid=true, lastToken=notoken] 
Refresh Catalog for FR with DB 
FR = Catalog [list size is : 30 valid=true, lastToken=notoken] 

Katalog ist eine Klasse mit einer Arraylist, ein boolean und einem String. Alles scheint richtig zu sein: UK soll leer sein, aber nicht null und FR soll 30 Produkte enthalten.

Ich kann immer noch nicht auf diese Daten in anderen Servlets zugreifen.

+0

Danke für die Bearbeitung, Englisch ist nicht meine Muttersprache, wie Sie sehen können. Grundsätzlich: ConcurrentHashMap mit Daten -> ServletContext dann ServletContext -> ConcurrentHashMap ohne Daten –

+0

Würde es Ihnen etwas ausmachen, den Code des "Servlet, das alles anzeigen ..." zu teilen? –

+0

Danke für Ihren Rat. Der "minimierte" Code ist nur der Code ohne Kommentare und Javadoc-Annotationen. Ich werde dieses Wort löschen, das verwirrend ist. Ich habe ein Update, ich arbeite gerade daran –

Antwort

0

fand ich den Ursprung des Problems, ein Anfängerfehler wie erwartet:

ich auf diese Weise zu aktualisieren versucht, vorausgesetzt, es ist das Objekt direkt in der

((Catalog)entry.getValue()).refreshdb((String) entry.getKey()); 

I ConcurrentHashMap aktualisiert hätte Ersetzen Sie es durch:

Catalog myCatalog = (Catalog)entry.getValue(); 
myCatalog.refreshdb((String) entry.getKey()); 
myMap.put((String)entry.getKey(), myCatalog); 

Und es funktioniert jetzt.

Ich weiß immer noch nicht, warum meine Objekte vom Zuhörer zugänglich waren, sie sollen nicht so funktionieren. Vielleicht ein seltsames Verhalten von meinem Server? Wie auch immer, dieses Problem ist behoben.

Danke an BalusC für seine Hilfe.