2013-02-12 26 views
5

मैं अपने विकेट ऐप में क्रमबद्धता बंद करना चाहता हूं और रैम में सभी पेज/सत्र जानकारी स्टोर करना चाहता हूं। मेरे आवेदन में बहुत कम संख्या में उपयोगकर्ता हैं (आमतौर पर 1); मुझे क्लस्टर परिनियोजन की आवश्यकता नहीं है; और मुझे अनुरोधों के बीच कुछ गैर-धारावाहिक डेटा कैश करने की आवश्यकता है।मैं विकेट 1.5 में क्रमबद्धता को कैसे अक्षम कर सकता हूं?

क्या कोई तरीका है ताकि विकेट स्वचालित रूप से मेरे पृष्ठों/सत्र को क्रमबद्ध करने का प्रयास नहीं करेगा? मैंने https://cwiki.apache.org/confluence/display/WICKET/Page+Storage पर HttpSessionDataStore का उपयोग करने के लिए सुझाव का प्रयास किया, लेकिन इसका कोई प्रभाव नहीं पड़ा। मैं अभी भी इस तरह स्टैक ट्रेस मिलती है:

SEVERE: Error serializing object class com.prosc.safetynet.Administer [object=[Page class = com.prosc.safetynet.Administer, id = 0, render count = 1]] 
org.apache.wicket.util.io.SerializableChecker$WicketNotSerializableException: Unable to serialize class: com.prosc.safetynet.SafetyNetSession$1 
Field hierarchy is: 
    0 [class=com.prosc.safetynet.Administer, path=0] 
    java.lang.Object org.apache.wicket.Component.data [class=org.apache.wicket.model.CompoundPropertyModel] 
     private java.lang.Object org.apache.wicket.model.CompoundPropertyModel.target [class=com.prosc.safetynet.SafetyNetSession$2] 
     final com.prosc.safetynet.SafetyNetSession com.prosc.safetynet.SafetyNetSession$2.this$0 [class=com.prosc.safetynet.SafetyNetSession] 
      private java.lang.Object com.prosc.safetynet.SafetyNetSession.tryAndSerializeMeBitch [class=com.prosc.safetynet.SafetyNetSession$1] <----- field that is not serializable 
    at org.apache.wicket.util.io.SerializableChecker.internalCheck(SerializableChecker.java:395) 
    at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:374) 
    at org.apache.wicket.util.io.SerializableChecker.checkFields(SerializableChecker.java:655) 
    at org.apache.wicket.util.io.SerializableChecker.internalCheck(SerializableChecker.java:578) 
    at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:374) 
    at org.apache.wicket.util.io.SerializableChecker.checkFields(SerializableChecker.java:655) 
    at org.apache.wicket.util.io.SerializableChecker.internalCheck(SerializableChecker.java:578) 
    at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:374) 
    at org.apache.wicket.util.io.SerializableChecker.checkFields(SerializableChecker.java:655) 
    at org.apache.wicket.util.io.SerializableChecker.internalCheck(SerializableChecker.java:578) 
    at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:374) 
    at org.apache.wicket.util.io.SerializableChecker.checkFields(SerializableChecker.java:655) 
    at org.apache.wicket.util.io.SerializableChecker.internalCheck(SerializableChecker.java:578) 
    at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:374) 
    at org.apache.wicket.util.io.SerializableChecker.writeObjectOverride(SerializableChecker.java:724) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
    at org.apache.wicket.serialize.java.JavaSerializer$CheckerObjectOutputStream.writeObjectOverride(JavaSerializer.java:258) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
    at org.apache.wicket.serialize.java.JavaSerializer.serialize(JavaSerializer.java:77) 
    at org.apache.wicket.pageStore.DefaultPageStore.serializePage(DefaultPageStore.java:368) 
    at org.apache.wicket.pageStore.DefaultPageStore.storePage(DefaultPageStore.java:146) 
    at org.apache.wicket.page.PageStoreManager$PersistentRequestAdapter.storeTouchedPages(PageStoreManager.java:383) 
    at org.apache.wicket.page.RequestAdapter.commitRequest(RequestAdapter.java:171) 
    at org.apache.wicket.page.AbstractPageManager.commitRequest(AbstractPageManager.java:94) 
    at org.apache.wicket.page.PageManagerDecorator.commitRequest(PageManagerDecorator.java:68) 
    at org.apache.wicket.page.PageAccessSynchronizer$2.commitRequest(PageAccessSynchronizer.java:281) 
    at org.apache.wicket.Application$2.onDetach(Application.java:1598) 
    at org.apache.wicket.request.cycle.RequestCycleListenerCollection$3.notify(RequestCycleListenerCollection.java:99) 
    at org.apache.wicket.request.cycle.RequestCycleListenerCollection$3.notify(RequestCycleListenerCollection.java:97) 
    at org.apache.wicket.util.listener.ListenerCollection$1.notify(ListenerCollection.java:119) 
    at org.apache.wicket.util.listener.ListenerCollection.reversedNotify(ListenerCollection.java:143) 
    at org.apache.wicket.util.listener.ListenerCollection.reversedNotifyIgnoringExceptions(ListenerCollection.java:113) 
    at org.apache.wicket.request.cycle.RequestCycleListenerCollection.onDetach(RequestCycleListenerCollection.java:95) 
    at org.apache.wicket.request.cycle.RequestCycle.onDetach(RequestCycle.java:603) 
    at org.apache.wicket.request.cycle.RequestCycle.detach(RequestCycle.java:542) 
    at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:287) 
    at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188) 
    at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:244) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870) 
    at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665) 
    at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528) 
    at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81) 
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685) 
    at java.lang.Thread.run(Thread.java:680) 

उत्तर

5

आप अपना खुद का आईपेज स्टोर लागू कर सकते हैं जो पृष्ठों को स्मृति में रखता है।

+0

यह काम करता है, धन्यवाद –

+0

एक उदाहरण भी है: http://maciej-miklas.blogspot.de/2013/09/wicket-6-disable-page-serialization.html –

1

मैं विशिष्ट कुछ भी विकेट के बारे में टिप्पणी नहीं कर सकता, लेकिन आम तौर पर एक HTTP Session की पूरी बात बोल अनुरोध (और संकुल वातावरण में, के बीच Serializable राज्य स्टोर करने के लिए है नोड विफलता की स्थिति में अनावश्यकता प्रदान करने के लिए उस स्थिति को क्लस्टर में एकाधिक नोड्स में दोहराने की अनुमति दें)। Serializable में कुछ ऐसा डालने को आम तौर पर एक त्रुटि माना जाता है, जैसा कि आपके स्टैक ट्रेस द्वारा दिखाया गया है। मुझे कुछ आश्चर्य होगा कि अगर कोई कॉन्फ़िगरेशन विकल्प है जो इसे बदल देगा (हालांकि शायद वहां है, जैसा कि मैंने कहा था कि मैं वास्तव में चीजों के विकेट पक्ष पर टिप्पणी नहीं कर सकता)।

एक साधारण विकल्प, यदि आपको सच्चे दृढ़ता की आवश्यकता नहीं है और यदि डेटा असाधारण रूप से बड़ा/जटिल नहीं है, तो प्रासंगिक स्थिति का ट्रैक रखने के लिए अपने पृष्ठ पर छिपे हुए फॉर्म फ़ील्ड का उपयोग करना है।

लेकिन यदि आप चाहते हैं कि एक मेमोरी कैश है, तो अपना खुद का कार्यान्वयन क्यों न करें? यह काफी सरल करना है:

public class SessionCache { 
    private static final Map<String, Map<String, Object>> CACHE = Collections.synchronizedMap(new HashMap<String, Map<String, Object>>()); 

    public static Object getAttribute(String sessionId, String attribName) { 
     Map<String, Object> attribs = CACHE.get(sessionId); 
     if (attribs != null) { 
      synchronized(attribs) { 
       return attribs.get(attribName); 
      } 
     } 

     return null; 
    } 

    public static void setAttribute(String sessionId, String attribName, Object attribValue) { 
     Map<String, Object> attribs = CACHE.get(sessionId); 
     if (attribs == null) { 
      attribs = new HashMap<String, Object>(); 
      CACHE.put(sessionId, attribs); 
     } 

     synchronized(attribs) { 
      attribs.put(attribName, attribValue); 
     } 
    } 

    public static void destroySession(String sessionId) { 
     CACHE.remove(sessionId); 
    } 

    public static void createSession(String sessionId, boolean force) { 
     if (force || ! CACHE.containsKey(sessionId)) { 
      CACHE.put(sessionId, new HashMap<String, Object>()); 
     } 
    } 
} 

नोट आप हुक करने कि विकेट के सत्र जीवन चक्र में इतना है कि पुराने सत्र निकाल दिए जाते हैं जब वे समय सीमा समाप्त हो चाहता हूँ कि। अन्यथा आपके हाथों पर धीरे-धीरे स्मृति रिसाव होगा। दस्तावेज़ों से ऐसा लगता है कि आप इसे registerUnboundListener()HttpSessionStore कक्षा पर पूरा कर सकते हैं।

+0

मैं बहुत यकीन है कि यह एक विकेट-विशिष्ट मुद्दा है कर रहा हूँ । स्टैक ट्रेस से पता चलता है कि यह सर्वलेट कंटेनर द्वारा शुरू नहीं किया जा रहा है; यह एक विकेट विधि है जो पृष्ठ को पेजमैप में स्टोर करने का प्रयास कर रही है। –

+0

अधिक विशिष्ट होने के लिए, serialization सामान यहां हो रहा है: org.apache.wicket.Aplication $ 2.onDetach (Application.java:1598) –

+0

इस समस्या का यह विशिष्ट उदाहरण विकेट वर्ग के कारण हो सकता है, लेकिन अवधारणात्मक रूप से [समान मुद्दा टॉमकैट के साथ मौजूद है] (http://dev-answers.blogspot.com.au/2007/03/how-to-turn-off-tomcat-session.html) (और मुझे किसी भी अन्य सर्वलेट कंटेनर के साथ संदेह है)। – aroth

1

यहां समाधान है जो मैं स्वेनमीयर के उत्तरों के आधार पर आया था। मुझे यकीन है कि यह नहीं 100% सही है, लेकिन यह मेरे परीक्षण में ठीक काम कर रहा है:

package com.prosc.wicket; 

import org.apache.wicket.Application; 
import org.apache.wicket.DefaultPageManagerProvider; 
import org.apache.wicket.page.IManageablePage; 
import org.apache.wicket.page.IPageManagerContext; 
import org.apache.wicket.pageStore.IDataStore; 
import org.apache.wicket.pageStore.IPageStore; 
import org.apache.wicket.pageStore.memory.HttpSessionDataStore; 
import org.apache.wicket.pageStore.memory.PageNumberEvictionStrategy; 

import java.io.Serializable; 
import java.util.HashMap; 
import java.util.Map; 

/** 
* This class disables Wicket's serialization behavior, while still retaining session and page data in memory (so back button will work). 
* This will run out of memory under heavy load; but it's very convenient for low volume web applications. 
* To disable serialization in your application, call this code: 
* <pre> 
*  setPageManagerProvider(new NoSerializePageManagerProvider(this, getPageManagerContext())); 
* </pre> 
*/ 
public class NoSerializePageManagerProvider extends DefaultPageManagerProvider { 
    private IPageManagerContext pageManagerContext; 

    public NoSerializePageManagerProvider(Application application, IPageManagerContext pageManagerContext) { 
     super(application); 
     this.pageManagerContext = pageManagerContext; 
    } 

    @Override 
    protected IDataStore newDataStore() { 
     return new HttpSessionDataStore(pageManagerContext, new PageNumberEvictionStrategy(20)); 
    } 

    @Override 
    protected IPageStore newPageStore(IDataStore dataStore) { 
     return new IPageStore() { 
      Map<String,Map<Integer,IManageablePage>> cache = new HashMap<String, Map<Integer, IManageablePage>>(); 

      public void destroy() { 
       cache = null; 
      } 

      public IManageablePage getPage(String sessionId, int pageId) { 
       Map<Integer, IManageablePage> sessionCache = getSessionCache(sessionId, false); 
       IManageablePage page = sessionCache.get(pageId); 
       if(page == null) { 
        throw new IllegalArgumentException("Found this session, but there is no page with id " + pageId); 
       } 
       return page; 
      } 

      public void removePage(String sessionId, int pageId) { 
       getSessionCache(sessionId, false).remove(pageId); 
      } 

      public void storePage(String sessionId, IManageablePage page) { 
       getSessionCache(sessionId, true).put(page.getPageId(), page); 
      } 

      public void unbind(String sessionId) { 
       cache.remove(sessionId); 
      } 

      public Serializable prepareForSerialization(String sessionId, Object page) { 
       return null; 
      } 

      public Object restoreAfterSerialization(Serializable serializable) { 
       return null; 
      } 

      public IManageablePage convertToPage(Object page) { 
       return (IManageablePage)page; 
      } 

      private Map<Integer, IManageablePage> getSessionCache(String sessionId, boolean create) { 
       Map<Integer, IManageablePage> sessionCache = cache.get(sessionId); 
       if(sessionCache == null) { 
        if(create) { 
         sessionCache = new HashMap<Integer, IManageablePage>(); 
         cache.put(sessionId, sessionCache); 
        } else { 
         throw new IllegalArgumentException("There are no pages stored for session id " + sessionId); 
        } 
       } 
       return sessionCache; 
      } 
     }; 
    } 
} 
1

मैं जेसी के जवाब में सुधार करना चाहते हैं। नीचे आंतरिक "कम से कम हाल ही में सम्मिलित किया गया" कैश के साथ IPageStore का एक धागा सुरक्षित कार्यान्वयन है (रहता प्रति सत्र के लिए अधिकतम 5 हाल ही में पहुंचे स्टेटफुल पृष्ठों पर):

public class CustomPageStore implements IPageStore { 

private static final Logger logger = LoggerFactory.getLogger(CustomPageStore.class); 

private static final int MEDIAN_OF_NUMBER_OF_SESSIONS = 6000; 

private ConcurrentMap<String, CustomLinkedHashMap<Integer, IManageablePage>> cache = new ConcurrentHashMap<>(MEDIAN_OF_NUMBER_OF_SESSIONS); 

@Override 
public void destroy() { 
    cache.clear(); 
} 

@Override 
public IManageablePage getPage(final String sessionId, int pageId) { 
    final Map<Integer, IManageablePage> sessionCache = getSessionCache(sessionId); 
    final RequestCycle requestCycle = RequestCycle.get(); 
    if (sessionCache == null) { 
     logger.warn("Missing cache. SessionId: {}, pageId: {}, URL: {}", sessionId, pageId, requestCycle == null ? StringUtils.EMPTY : requestCycle.getRequest().getUrl()); 
     return null; 
    } 

    final IManageablePage page; 
    //noinspection SynchronizationOnLocalVariableOrMethodParameter 
    synchronized (sessionCache) { 
     page = sessionCache.get(pageId); 
    } 

    if (page == null && logger.isDebugEnabled()) { 
     logger.debug("Missed page. SessionId: {}, pageId: {}, URL: {}", sessionId, pageId, requestCycle == null ? StringUtils.EMPTY : requestCycle.getRequest().getUrl()); 
    } 

    return page; 
} 

@Override 
public void removePage(final String sessionId, int pageId) { 
    final Map<Integer, IManageablePage> sessionCache = getSessionCache(sessionId); 
    if (sessionCache != null) { 
     //noinspection SynchronizationOnLocalVariableOrMethodParameter 
     synchronized (sessionCache) { 
      sessionCache.remove(pageId); 
     } 
    } 
} 

@Override 
public void storePage(final String sessionId, IManageablePage page) { 
    final LinkedHashMap<Integer, IManageablePage> sessionCache = getOrCreateSessionCache(sessionId); 
    final int pageId = page.getPageId(); 
    //noinspection SynchronizationOnLocalVariableOrMethodParameter 
    synchronized (sessionCache) { 
     if (sessionCache.containsKey(pageId)) { 
      // do this to change insertion order and update least inserted entry 
      sessionCache.remove(pageId); 
      sessionCache.put(pageId, page); 
     } else { 
      sessionCache.put(pageId, page); 
     } 
    } 
} 

@Override 
public void unbind(final String sessionId) { 
    cache.remove(sessionId); 
} 

@Override 
public Serializable prepareForSerialization(String sessionId, Object page) { 
    return null; 
} 

@Override 
public Object restoreAfterSerialization(Serializable serializable) { 
    return null; 
} 

@Override 
public IManageablePage convertToPage(final Object page) { 
    return (IManageablePage) page; 
} 

@Nullable 
private Map<Integer, IManageablePage> getSessionCache(final String sessionId) { 
    return cache.get(sessionId); 
} 

@Nonnull 
private CustomLinkedHashMap<Integer, IManageablePage> getOrCreateSessionCache(final String sessionId) { 
    return cache.computeIfAbsent(sessionId, s -> new CustomLinkedHashMap<>()); 
} 

/** Mimics "least recently inserted" cache */ 
private static class CustomLinkedHashMap<K, V> extends LinkedHashMap<K, V> { 

    /** use this parameter to control memory consumption and frequency of appearance of PageExpiredException */ 
    private static final int MAX_PAGES_PER_SESSION = 5; 

    @Override 
    protected boolean removeEldestEntry(final Map.Entry<K, V> eldest) { 
     return size() > MAX_PAGES_PER_SESSION; 
    } 
} 
} 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^