GWT RequestFactory: प्रति अनुरोध एकल EntityManager का उपयोग कैसे करें




code-injection cdi (3)

RequestFactory संलग्न संस्थाओं को जारी RequestFactory लिए, मुझे यह सुनिश्चित करना होगा कि मैं प्रत्येक अनुरोध के लिए एक ही इकाई RequestFactory का उपयोग करूँ।

मैं ThreadLocal कार्यान्वयन के आधार पर अपनी फैक्टरी कक्षा को एक साथ ThreadLocal , लेकिन मुझे यकीन नहीं है कि संसाधनों को ठीक से कैसे उजागर करना है (उदाहरण के लिए कैसे पता है कि अनुरोध समाप्त हो गया है और कॉल close() करें close() )

क्या यह सुनिश्चित करने का एक आसान तरीका है कि एक एकल इकाई प्रबंधक पूर्ण पूर्ण जे 2 ईई / सीडीआई के बिना दिए गए ServletRequest के दौरान उपयोग किया जाता है? यदि मुझे चाहिए तो मैं उस मार्ग को ले जाऊंगा, लेकिन मैं चीजों को सरल रखने की उम्मीद कर रहा था, खासकर जब से मैं हल्के विकास सर्वर का उपयोग करना जारी रखना चाहता हूं जो कि जीडब्ल्यूटी के साथ आता है।


जीडब्ल्यूटी गूगल समूह और बीबीवी के फीडबैक के आधार पर, जो अंत में मैं अंत में आया हूं, वह है I

EntityManager के लिए एक धागा-स्थानीय धारक बनाएं; अपनी संस्थाओं में इसका संदर्भ दें जब उन्हें एक EntityManager प्राप्त करने की आवश्यकता होती है:

public class ThreadLocalEntityManager
{
    private static ThreadLocal<EntityManager> holder = new ThreadLocal<EntityManager>();

    private ThreadLocalEntityManager()
    {
    }

    public static EntityManager get()
    {
        return holder.get();
    }

    public static void set(EntityManager em)
    {
        holder.set(em);
    }
}

फिर एक फ़िल्टर बनाएं जो कि अनुरोध के लिए प्रारंभिक इकाई प्रबंधक सेट करेगा:

public class PersistenceFilter implements Filter
{
    protected static final Logger log = Logger.getLogger(PersistenceFilter.class.getName());
    private EntityManagerFactory factory;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        factory = Persistence.createEntityManagerFactory("my_persistence");
    }

    @Override
    public void destroy()
    {
        factory.close();
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
    {
        EntityManager em = factory.createEntityManager();
        ThreadLocalEntityManager.set(em);

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try
        {
            chain.doFilter(req, res);
            tx.commit();
        }
        catch (Exception e)
        {
            tx.rollback();
        }
        finally
        {
            log.info("closing EntityManager: " + EMF.entityManager());
            em.close();
        }

    }
}

फिर / gwtRequest यूआरएल पैटर्न में फ़िल्टर लागू करें:

<filter>
    <filter-name>PersistenceFilter</filter-name>
    <filter-class>com.example.PersistenceFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>PersistenceFilter</filter-name>
    <url-pattern>/gwtRequest</url-pattern>
</filter-mapping>

ध्यान दें कि यहां एक दोष है- एक एंटिटी मैनेजर प्रत्येक अनुरोध के लिए बनाया गया है जो इस सर्वलेट के माध्यम से चला जाता है, चाहे वह आपके अंतर्निहित कोड द्वारा उपयोग किया गया हो या नहीं। संभवत: इसे और अधिक मजबूत बनाने के लिए खड़े हो सकते हैं और किसी तरह तरह से आजीवन इकाई प्रबंधक (और लेनदेन) को केवल जब अनुरोध किया जाता है

लेकिन अभी तक यह कोड RequestFactory साथ अच्छी तरह से काम करने लगता है सुधार के सुझावों का अत्यधिक स्वागत किया गया

नोट: इस अनुभव ने मुझे सिखाया है कि यह संभवतः इस तरह के टुकड़े को लागू करने की कोशिश करने की बजाय पूर्ण सीडीआई पर जाने के लायक है इस परियोजना के दौरान इस कदम के लिए मेरे पास अभी तक उपलब्ध नहीं था।


DynaTableRf नमूना ऐप अपने web.xml फ़ाइल में एक दृढ़ संदर्भ सेट करने के लिए सर्वलेट फ़िल्टर जोड़कर कुछ समान करता है। वैकल्पिक रूप से, आप RequestFactoryServlet subclass कर सकते हैं और super.doPost() रिटर्न जब finally ब्लॉक में EntityManager नीचे फाड़ करने के लिए अपने doPost() विधि ओवरराइड सकता है।


यदि आप स्प्रिंग का उपयोग कर रहे हैं तो आपको केवल अपने वेब। एक्सएमएल को ओपनएन्टीआईटीएनेटिएन्जर इनव्यू सर्वलेट फ़िल्टर जोड़ना होगा।

<filter>
    <filter-name>entityManagerFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>entityManagerFilter</filter-name>
    <url-pattern>/gwtRequest</url-pattern>
</filter-mapping>