2012-12-20 39 views
57

मैं JBoss अनुप्रयोग सर्वर 7 करने के लिए एक वेब सेवाओं घटक को तैनात RESTEasy JAX-आरएस कार्यान्वयन का उपयोग करने में आवश्यक @QueryParam।JAX-आरएस (और क्या उनकी अनुपस्थिति में करने के लिए)

वहाँ एक एनोटेशन आवश्यक घोषित करने के लिए उपलब्ध अनिवार्य @QueryParam JAX-आरएस में पैरामीटर है? और, यदि नहीं, तो ऐसे मानकों से निपटने के लिए 'मानक' तरीका क्या है जहां ऐसे पैरामीटर गुम हैं?

मेरी वेब सेवा (संसाधन) विधियां जेएसओएन-स्ट्रिफाइड परिणामों को वापस लौटती हैं जब सभी अनिवार्य तर्कों के साथ सही तरीके से बुलाया जाता है, लेकिन मुझे यकीन नहीं है कि कॉलर को इंगित करने का सबसे अच्छा तरीका क्या है कि एक आवश्यक पैरामीटर गुम हो गया था।

+4

आप एक '@ DefaultValue' टिप्पणी जोड़ने और एक उचित मूल्य जब भी यह याद आ रही है करने के लिए पैरामीटर सेट कर सकते हैं। यदि आपके पास डिफ़ॉल्ट मान नहीं है और पैरामीटर वास्तव में महत्वपूर्ण है, तो शायद आपको 'शून्य' के लिए param जांचना चाहिए और '400 खराब अनुरोध 'स्थिति कोड वापस करना चाहिए। – toniedzwiedz

उत्तर

62

अच्छा सवाल। दुर्भाग्य से (या शायद सौभाग्य से) किसी भी पैरा को अनिवार्य बनाने के लिए जेएक्स-आरएस में कोई तंत्र नहीं है। यदि पैरामीटर की आपूर्ति नहीं की जाती है तो इसका मान NULL होगा और आपके संसाधन को इसके अनुसार सौदा करना चाहिए। मैं WebApplicationException उपयोग करने के लिए अपने उपयोगकर्ताओं को सूचित करने के लिए सिफारिश करेंगे:

@GET 
@Path("/some-path") 
public String read(@QueryParam("name") String name) { 
    if (name == null) { 
    throw new WebApplicationException(
     Response.status(HttpURLConnection.HTTP_BAD_REQUEST) 
     .entity("name parameter is mandatory") 
     .build() 
    ); 
    } 
    // continue with a normal flow 
} 
+12

[जेएक्स-आरएस 1.0 के लिए प्रलेखन] (https://wikis.oracle.com/display/Jersey/Overview+of+JAX-RS+1.0+ विशेषताएं) कहता है कि यह हमेशा शून्य नहीं होगा। यह "सूची, सेट या सॉर्टेडसेट के लिए एक खाली संग्रह होगा, अन्य ऑब्जेक्ट प्रकारों के लिए शून्य, और जावा-परिभाषित डिफ़ॉल्ट के लिए डिफ़ॉल्ट प्रकार होगा।" – hotshot309

+2

'स्ट्रिंग' एक आदिम प्रकार की नहीं है, तो यह" अन्य वस्तु प्रकार के लिए अशक्त "है – yegor256

+10

इसके अलावा HttpURLConnection.HTTP_BAD_REQUEST का उपयोग नहीं करने की सलाह देते हैं, बल्कि javax.ws.rs.core.Response.Status.BAD_REQUEST विधि के साथ रखने में रहने के लिए अपेक्षित पैरामीटर – cmonkey

45

आप लागू करने के लिए है, जो पैरामीटर उन्हें @javax.validation.constraints.NotNull साथ एनोटेट द्वारा अनिवार्य हैं javax.validation व्याख्या का उपयोग कर सकते हैं। an example for Jersey और one for RESTeasy देखें।

तो अपने विधि बस बन जाएगा:

@GET 
@Path("/some-path") 
public String read(@NotNull @QueryParam("name") String name) { 
    String something = 
    // implementation 
    return something; 
} 

ध्यान दें कि अपवाद फिर कुछ त्रुटि कोड के लिए JAX-आरएस प्रदाता द्वारा अनुवादित हो जाता है। इसे javax.ws.rs.ext.ExceptionMapper<javax.validation.ValidationException> के अपने कार्यान्वयन को पंजीकृत करके आमतौर पर ओवरराइड किया जा सकता है।

यह त्रुटि प्रतिक्रियाओं के लिए अनिवार्य पैरामीटर का अनुवाद करने का एक केंद्रीकृत तरीका प्रदान करता है और कोई कोड डुप्लिकेशन आवश्यक नहीं है।

+11

इस दृष्टिकोण के साथ एक मुद्दा यह है कि त्रुटि संदेश अनुपस्थित पैरामीटर का नाम निर्दिष्ट नहीं करता है, जैसे "arg1 शून्य नहीं हो सकता"। सौभाग्य से बीन प्रमाणीकरण spec इंटरफ़ेस javax.validation.ParameterNameProvider पेश किया। जेएक्स-आरएस के लिए हम नाम पाने के लिए एनरेशन क्वरीपाराम और पथपाराम का उपयोग कर सकते हैं (क्योंकि प्रतिबिंब पैरामीटर नाम लाने की अनुमति नहीं देता है)। एक उदाहरण यहां पाया जा सकता: http://stackoverflow.com/q/22496527/998772 –

+0

हाँ मुझे लगता है कि दर्द के माध्यम से चला गया और [इसके बारे में सवाल] एक से पूछा (http://stackoverflow.com/questions/22567097/jersey- सेम के सत्यापन-parameternameprovider)। यह करने योग्य है, लिखने के लिए बस थोड़ा और कोड। –

+0

मैं इसी तरह की चीज करने की कोशिश कर रहा हूं लेकिन अगर मैं यूआरएल से यह क्वेरी पैरामीटर छोड़ देता हूं तो भी @NotNull इसका पता नहीं लगा रहा है। मैं एक धागा यहाँ शुरू कर दिया है [कड़ी] (http://stackoverflow.com/questions/25737837/notnull-annotation-is-not-checking-null-queryparameter-in-jersey-rest-resource) – PST

14

मैं एक ही समस्या में पड़ गए और फैसला किया है कि मैं एक gazillion बॉयलरप्लेट अशक्त मेरी बाकी कोड में फैले चेकों नहीं करना चाहता था, तो यह यह है मैं क्या करने का फैसला किया क्या:

  1. एक एनोटेशन है कि एक का कारण बनता है बनाएं एक आवश्यक पैरामीटर निर्दिष्ट नहीं होने पर अपवाद को अपवादित किया जाना चाहिए।
  2. फेंक दिया अपवाद संभाल लें वैसे ही मैं अपने आरईएसटी कोड में फेंकने वाले सभी अन्य अपवादों को संभालता हूं।

लिए 1), मैं निम्नलिखित एनोटेशन कार्यान्वित:

import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Target(ElementType.PARAMETER) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface Required 
{ 
    // This is just a marker annotation, so nothing in here. 
} 

... और निम्नलिखित JAX-आरएस ContainerRequestFilter यह लागू करने के लिए:

import java.lang.reflect.Parameter; 
import javax.ws.rs.QueryParam; 
import javax.ws.rs.container.ContainerRequestContext; 
import javax.ws.rs.container.ContainerRequestFilter; 
import javax.ws.rs.container.ResourceInfo; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.ext.Provider; 

@Provider 
public class RequiredParameterFilter implements ContainerRequestFilter 
{ 
    @Context 
    private ResourceInfo resourceInfo; 

    @Override 
    public void filter(ContainerRequestContext requestContext) 
    { 
     // Loop through each parameter 
     for (Parameter parameter : resourceInfo.getResourceMethod().getParameters()) 
     { 
      // Check is this parameter is a query parameter 
      QueryParam queryAnnotation = parameter.getAnnotation(QueryParam.class); 

      // ... and whether it is a required one 
      if (queryAnnotation != null && parameter.isAnnotationPresent(Required.class)) 
      { 
       // ... and whether it was not specified 
       if (!requestContext.getUriInfo().getQueryParameters().containsKey(queryAnnotation.value())) 
       { 
        // We pass the query variable name to the constructor so that the exception can generate a meaningful error message 
        throw new YourCustomRuntimeException(queryAnnotation.value()); 
       } 
      } 
     } 
    } 
} 

आप रजिस्टर करने की आवश्यकता ContainerRequestFilter उसी तरह आप अपने JAX-RS लाइब्रेरी के साथ अन्य @Provider कक्षाएं पंजीकृत करेंगे। शायद रीस्टेसी आपके लिए स्वचालित रूप से करता है।

लिए 2), मैं एक सामान्य JAX-आरएस ExceptionMapper का उपयोग करके सभी क्रम अपवाद संभाल:

import javax.ws.rs.core.Response; 
import javax.ws.rs.ext.ExceptionMapper; 
import javax.ws.rs.ext.Provider; 

@Provider 
public class MyExceptionMapper implements ExceptionMapper<RuntimeException> 
{ 
    @Override 
    public Response toResponse(RuntimeException ex) 
    { 
     // In this example, we just return the .toString() of the exception. 
     // You might want to wrap this in a JSON structure if this is a JSON API, for example. 
     return Response 
      .status(Response.Status.BAD_REQUEST) 
      .entity(ex.toString()) 
      .build(); 
    } 
} 

पहले की तरह, अपने JAX-आरएस पुस्तकालय के साथ वर्ग रजिस्टर करने के लिए याद है।

+1

इस प्रस्ताव को कुछ करता है कि @ javax.validation.constraints.NotNull नहीं करेगा? –

+1

@MichaelHaefele यह पैरामीटर नाम को बरकरार रखता है, जो एक सार्थक त्रुटि संदेश दिखाने के लिए उपयोगी है। यदि आप 'NotNull' एनोटेशन का उपयोग करते हैं, तो दुर्भाग्यपूर्ण है, तो पैरामीटर नाम खो जाता है। यही वह मुद्दा था जिसने मुझे अपनी टिप्पणी लिख दी। लेकिन यह भी https://stackoverflow.com/questions/13968261/required-queryparam-in-jax-rs-and-what-to-do-in-their-absence/31893626?noredirect=1#comment35934905_21920512 देखते हैं। जब से मैंने यह कोड लिखा था, हालात बदल सकते हैं। – Zero3