2017-10-13 6 views
0

Ich habe die folgende Einheit verbieten:Wie Schrägstrich '/' Verwendung in Entitätsattribut mit jaxb und jaxrs

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = EntityConstants.PARTNER) 
public class FilePartner 
{ 
    @XmlAttribute(name = EntityConstants.IDENTIFIER, required = true) 
    @XmlJavaTypeAdapter(RestResourceIdJaxbAdapter.class) 
    private String identifier; 
    ... 
} 

Hier ist der jaxb Adapter:

public class RestResourceIdJaxbAdapter extends XmlAdapter<String, String> 
{ 
    @Override 
    public String unmarshal(String v) throws Exception 
    { 
     if (v != null && v.contains("/")) 
     { 
      // throw new ApiException(Status.BAD_REQUEST, RestErrorMessages.BAD_REQUEST_SUFFIX, "Identifier must not contain slashes"); 

      return v.replaceAll("/", ""); 
     } 

     return v; 
    } 

    @Override 
    public String marshal(String v) throws Exception 
    { 
     return v; 
    } 
} 

Ich habe einen jaxrs Dienst, POST-Anfragen mit Körper FilePartner akzeptiert:

@POST 
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    public Response createPartner(FilePartner partner, 
            @Context UriInfo uriInfo, 
            @HeaderParam(HttpHeaders.ACCEPT) String acceptHeader) 
     throws ApiException 
    { 
     ... 
    } 

Was will ich erreichen, ist die Verwendung von Schrägstrichen ‚/‘ in der ich zu verbieten Bekennerattribut der FilePartner-Entität. Heute mache ich dies mit einem Jaxb-Adapter, der einfach alle Schrägstriche aus der ID entfernt, wenn das Programm entfernt wird. Stattdessen möchte ich eine entsprechende BAD_REQUEST-Ausnahme für den Benutzer zurückgeben.

Ich habe versucht, Ausnahme in der Unmarshal-Methode des Jaxb-Adapters zu werfen, aber scheint, dass Jaxrs es schluckt und einfach meine Kennung auf null setzt. Wenn wir dieses Verhalten überschreiben möchten, muss ich einen neuen @Provider erstellen und einen speziellen ValidationEventHandler im unmarshaller registrieren, den javax.ws.rs.ext.MessageBodyReader erstellt. Leider ist dies unmöglich, wenn ich nicht explizit eine Abhängigkeit zu einer JAX-RS-Implementierung definiere, die ich vermeiden möchte.

Gibt es andere Optionen, um die Verwendung von Schrägstrichen im Bezeichnerattribut zu beschränken, ohne eine explizite Abhängigkeit zu Jersey/Resteasy zu definieren und ohne die Einschränkung in der @ POST-Methode des Dienstes zu behandeln?

+0

Warum suchen Sie nicht nach Schrägstrich in Post-Methode selbst (ohne Anpassung) und Fehler – Optional

+0

Ich wünschte, ich könnte es deklarativ tun. Ich habe das in der Frage erklärt. Die Sache ist - ich habe Dutzende ähnlicher Restdienste, die sich mit verschiedenen, aber auch sehr ähnlichen Arten von Entitäten befassen. Ich möchte nicht alle Restdienst-POST-Methoden ändern, stattdessen möchte ich lieber alle Entitäten kommentieren. Man könnte meinen, dass dies ein gebräuchlicher und sehr standardmäßiger Anwendungsfall ist. Ich frage mich, warum es nicht einfach ist, deklarativ zu implementieren. – mdzh

+0

Ok @mdzh lassen Sie mich verstehen. Ich denke wir können es lösen :). Sie haben eine Entität für mehrere Ruheaufrufe freigegeben und möchten nur in einer Operation für dieselbe Entität "/" verhindern. Oder Sie haben viele Entitäten und wollen nur eine Entität auf _nicht_ haben ein "/" – Optional

Antwort

0

zu Ihrer Rettung kommt ReaderInterceptor

Sie eine spezielle Handhabung @XmlJavaTypeAdapter mit nicht tun. Registrieren Sie eine ReaderInterceptor mit Ihrer Application-Klasse (wenn in Jersey2) oder früher in web.xml.

import java.io.IOException; 

import javax.ws.rs.WebApplicationException; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.ext.Provider; 
import javax.ws.rs.ext.ReaderInterceptor; 
import javax.ws.rs.ext.ReaderInterceptorContext; 
javax.ws.rs.ext.ReaderInterceptor 

@Provider 
public class ValidationInterceptor implements ReaderInterceptor { 
    public ValidationInterceptor() { 
     super(); 
    } 

    @Override 
    public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException, 
                          WebApplicationException { 
     Object o = readerInterceptorContext.proceed(); 
     if (o instanceof FilePartner&& ((FilePartner) o).getIndentifier().contains("/")) { 
      throw new WebApplicationException(Response.status(400) 
                 .entity("Identifier must not contain a slash") 
                 .build()); 

     } 
     return o; 
    } 
} 

und registrieren Sie den Interceptor zu Ihrem Application in Überschreibung von public Set<Class<?>> getClasses() Methode so etwas wie classes.add(ValidationInterceptor.class);

Hoffnung, das hilft.

Verwandte Themen