2012-11-02 13 views
5

मुझे समझने में कुछ समस्या है कि क्यों @Context निर्भरता इंजेक्शन HttpServletRequest या HttpServletResponse की बजाय $ प्रॉक्सी (यादृच्छिक संख्या) उदाहरणों का संग्रह देता है।@Context HttpServletRequest के बजाय प्रॉक्सी लौटाता है (प्रॉक्सी के दायरे में कोई थ्रेड स्थानीय मान नहीं)

मैं ग्लासफ़िश 3.1.2.2 का उपयोग जर्सी के संस्करण (जर्सी: 1.11.1) के साथ कर रहा हूं और मेरा ऐप ईएआर एप्लिकेशन के रूप में बनाया गया है।

मेरे पास सरल @ रिमोट इंटरफ़ेस है जहां मैं अपनी विधियों और आरईएसटी सेवाओं को बिना किसी समस्या के काम करता हूं, लेकिन जिस क्षण मैं HttpServletRequest जानकारी तक पहुंचने का प्रयास करता हूं, यह केवल समस्याओं का कारण बनता है।

मैं अपने सत्र सेम में निजी क्षेत्रों टिप्पणी किए गए:

@POST 
@Path("authenticate") 
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
@Produces(MediaType.APPLICATION_JSON) 
public Response authenticate(@FormParam("username") String username, @FormParam("password") String password, @Context HttpServletRequest request, @Context HttpServletResponse response); 

जब मैं कोशिश करते हैं और सिर्फ विधि डिबग:

@Context 
private HttpServletRequest request; 
@Context 
private HttpServletResponse response; 

और यह भी बनाई गई विधि हस्ताक्षर मापदंडों के सेट के रूप में शामिल करने के लिए @Context एक प्रविष्टि के बाद मैं देख सकता हूं कि वैश्विक अनुरोध और प्रतिक्रिया वस्तुएं शून्य हैं जहां स्थानीय विधि उदाहरण $ ProxyXXX प्रकार के हैं।

समस्या यह है कि मैं इन वस्तुओं तक पहुंच नहीं सकता (या मुझे यकीन नहीं है)। वेब वे मेरे पास उपलब्ध होना चाहिए, लेकिन इस समय मैं इन तक पहुँचने का प्रयास पर ट्यूटोरियल के अनुसार, इस फेंक दिया जा रहा है:

WARNING: StandardWrapperValve[RestDataService]: PWC1406: Servlet.service() for servlet RestDataService threw exception 
java.lang.IllegalStateException: No thread local value in scope for proxy of class $Proxy245 
    at com.sun.jersey.server.impl.ThreadLocalInvoker.invoke(ThreadLocalInvoker.java:93) 
    at $Proxy245.getContextPath(Unknown Source) 

यह कैसे मैं इन (इस उदाहरण मैं बस फोन में कॉल करने के लिए कोशिश कर रहा हूँ है getContextPath)

@Override 
public Response authenticate(String username, String password, HttpServletRequest request, HttpServletResponse response) { 

    System.out.println("just a test: " + request.getContextPath()); 

मुझे यहां क्या याद आ रही है? क्या किसी ने भी इसी तरह की समस्या का अनुभव किया है?

ग्रेग

+0

मुझे कुछ समस्या हल हो गई है, आप संदर्भ ले सकते हैं -> http://stackoverflow.com/questions/14397971/spring-jetty-uriinfo-inject-is-null/14400039#14400039 –

उत्तर

0

नहीं एक ही मुद्दा मैं सत्र के समुचित वस्तुओं हो रही हूँ और यह मेरे लिए ठीक काम कर रहा context.like।

public login login(request Request,@Context MessageContext context) { 

       HttpServletRequest httpServletRequest = context 
           .getHttpServletRequest(); 

}

5

इस समस्या को आप को समझने के लिए काम scopes की जरूरत को समझने के लिए। वर्णन करने के लिए कि क्या होता है, यहां एक उदाहरण है। मान लीजिए आप इस

@Singleton 
@Path("..") 
public class SomeResource { 

    @Context 
    private HttpServletRequest request; 
} 

समस्या यह स्थिति है कि एक HttpServletRequest प्रत्येक अनुरोध के लिए उत्पन्न किया जाता है बन गया है, लेकिन संसाधन वर्ग, केवल एक बार बनाई गई है कि यह एक सिंगलटन नहीं है, इसलिए शुरू में है में इंजेक्षन करने के लिए कोई HttpServletRequest के रूप में सिंगलटन जब इसे बनाया जाता है।

इस समस्या को हल करने के लिए, जर्सी प्रॉक्सी इंजेक्ट करता है। तो धारणात्मक, परिणाम और अधिक की तरह

@Singleton 
@Path("..") 
public class SomeResource { 

    @Context 
    private ProxyHttpServletRequest proxyRequest; 
} 

जब अनुरोध में आता है, वास्तविक HttpServletRequest एक गुंजाइश संदर्भ में एक ThreadLocal में डाल दिया जाता है। यह एक सटीक कार्यान्वयन नहीं है, लेकिन आप की तरह

public class RequestScopeContext { 
    private static final ThreadLocal<HttpServletReqest> request 
      = new ThreadLocal<>(); 

    public static HttpServletRequest get() { .. } 
    public static void setRequest(HttpServletRequest request) { .. } 
} 

कुछ के रूप में एक गुंजाइश संदर्भ कल्पना कर सकते हैं अनुरोध HttpServletRequest में आता है संदर्भ में निर्धारित है।और के अंदर HttpServletRequest पर कॉल किए जाने पर, यह वास्तव में प्रॉक्सी ऑब्जेक्ट पर बनाया जाता है जो ThreadLocal और आगे के कॉल से अनुरोध प्राप्त करता है। वैचारिक रूप से, आप इसे

class ProxyHttpServletRequest { 
    public String getContextPath() { 
     HttpServletRequest request = RequestScopeContext.get(); 
     return request.getContextPath(); 
    } 
} 

की तरह कुछ देखने के लिए सोच भी अब मान लीजिए कि हम इस राशि के बजाय

@Singleton 
@Path("..") 
public class SomeResource { 

    @GET 
    public Response get(@Context HttpServletRequest request) { 
     ... 
    } 
} 

इस के साथ अंतर यह है कि अनुरोध अब एक क्षेत्र में इंजेक्ट किया जाता है, इसलिए कोई प्रॉक्सी की आवश्यकता है । HttpServletRequest केवल तभी जरूरी है जब विधि को कॉल किया जाए। तो जर्सी वास्तविक अनुरोध इंजेक्ट करेगा, न कि प्रॉक्सी।

बस ध्यान दें कि यह पैटर्न जर्सी के लिए विशिष्ट नहीं है। कोई ढांचा डीआई और स्कॉप्स शामिल थे, व्यापक स्कोप ऑब्जेक्ट्स में कम स्कोप ऑब्जेक्ट्स इंजेक्ट करने का प्रयास करते समय एक समान प्रॉक्सी पैटर्न का उपयोग करेंगे।


ओ पी करने के लिए: अब इस अपने सटीक समस्या नहीं है। उपर्युक्त उत्तर प्रॉक्सी के बारे में प्रश्न रखने वाले अधिकांश लोगों को अधिकतर लाभ देगा।

आपके मामले में, आप ने कहा आप एक @Remote EJB में HttpServletRequest इंजेक्षन करने की कोशिश कर रहे हैं। एक बात के लिए मुझे यह भी पता नहीं था कि संभव है। मेरा अनुमान है कि ईजेबी इंजन कभी भी ThreadLocal सेट नहीं करता है। तो जब जर्सी इसे कॉल करने की कोशिश करता है, तो संदर्भ में कुछ भी नहीं है।

@Context एनोटेशन जेएक्स-आरएस घटकों के लिए है, न कि ईजेबी के लिए। मैं व्यक्तिगत रूप से, एक ईजेबी में HttpServletRequest इंजेक्ट करने का तरीका नहीं जानता, क्योंकि मैं ईजेबी के साथ ज्यादा काम नहीं करता हूं। तो आपकी सटीक समस्या का सामना करने वाले किसी को भी कैसे करना है, इसकी खोज करने की आवश्यकता होगी। लेकिन जैसा कि मैंने कहा, मुझे नहीं लगता कि यह अधिकांश लोग हैं जो इस प्रश्न को खोजते हैं। मुझे लगता है कि वे बस सोच रहे हैं कि वास्तविक अनुरोध के बजाय अनुरोध प्रॉक्सी क्यों है। तो यह जवाब उनके प्रति अधिक तैयार है।

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