2010-08-06 2 views
10

JPA (EclipseLink) 엔티티의 CRUD 인터페이스 인 JAX-RS 웹 서비스 (저지)가 있습니다. 내 엔티티는 데이터베이스 테이블에서 자동 생성되었고 JAXB 주석으로 주석을 달아서 XML에서 마샬링/언 마샬링 될 수 있습니다. 필자의 리소스 메소드는 필요할 경우 JAXBElement 객체를 매개 변수로 사용합니다.JPA/JAX-RS 웹 서비스에서 JAXBElement를 확인하십시오.

저는 XSD가 없습니다. 그러나 요청에서받은 XML의 유효성을 검사하기 위해 기꺼이 작성할 것입니다. 그러나 검증을 시작하는 방법을 모르겠습니다. Jersey는 마샬링/언 마샬링을 자동으로 처리하고 있으며 유효성 검사와 관련된 모든 참조는 해당 수준에서 수행됩니다.

누군가이 방법을 보여주는 예제/학습서를 알고 있습니까?

감사합니다.

답변

15

사용자 정의 MessageBodyReader를 작성하여이를 처리 할 수 ​​있습니다. 아래의 고객 모델을 기반으로 예제는 :

import java.io.IOException; 
import java.io.InputStream; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.Type; 
import java.net.URL; 

import javax.ws.rs.Consumes; 
import javax.ws.rs.WebApplicationException; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.MultivaluedMap; 
import javax.ws.rs.ext.ContextResolver; 
import javax.ws.rs.ext.MessageBodyReader; 
import javax.ws.rs.ext.Provider; 
import javax.ws.rs.ext.Providers; 
import javax.xml.XMLConstants; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.validation.Schema; 
import javax.xml.validation.SchemaFactory; 

@Provider 
@Consumes("application/xml") 
public class ValidatingReader implements MessageBodyReader<Customer> { 

    @Context 
    protected Providers providers; 

    private Schema schema; 

    public ValidatingReader() { 
     try { 
      SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
      URL schemaURL = null; 
      schema = sf.newSchema(schemaURL); 
     } catch(Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2, MediaType arg3) { 
     return arg0 == Customer.class; 
    } 

    public Customer readFrom(Class<Customer> arg0, Type arg1, Annotation[] arg2, MediaType arg3, MultivaluedMap<String, String> arg4, InputStream arg5) 
      throws IOException, WebApplicationException { 
     try { 
      JAXBContext jaxbContext = null; 
      ContextResolver<JAXBContext> resolver = providers.getContextResolver(JAXBContext.class, arg3); 
      if(null != resolver) { 
       jaxbContext = resolver.getContext(arg0); 
      } 
      if(null == jaxbContext) { 
       jaxbContext = JAXBContext.newInstance(arg0); 
      } 
      Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 
      unmarshaller.setSchema(schema); 
      return (Customer) unmarshaller.unmarshal(arg5); 
     } catch(JAXBException e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 
+0

결국 스키마에 대해 유효성을 검사 할 필요가 없었지만 앞으로 필요할 경우 훌륭한 참조 정보입니다. – sdoca

9

우리는 한 단계 더 나아가 필요한 경우와 같이 하위 분류 될 수있는 일반적인 (추상) ValidatingReader을 만들 수 있습니다.

import java.io.IOException; 
import java.io.InputStream; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.ParameterizedType; 
import java.lang.reflect.Type; 

import javax.ws.rs.WebApplicationException; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.MultivaluedMap; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.ext.ContextResolver; 
import javax.ws.rs.ext.MessageBodyReader; 
import javax.ws.rs.ext.Providers; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 

public abstract class AbstractValidatingReader<T> implements 
    MessageBodyReader<T> { 

@Context 
protected Providers providers; 

@SuppressWarnings("unchecked") 
@Override 
public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2, 
     MediaType arg3) { 

    Class<T> readableClass = (Class<T>) ((ParameterizedType) getClass() 
      .getGenericSuperclass()).getActualTypeArguments()[0]; 
    return arg0 == readableClass; 
} 

@SuppressWarnings("unchecked") 
@Override 
public T readFrom(Class<T> arg0, Type arg1, Annotation[] arg2, 
     MediaType arg3, MultivaluedMap<String, String> arg4, 
     InputStream arg5) throws IOException, WebApplicationException { 

    T type = null; 
    JAXBContext jaxbContext = null; 
    ContextResolver<JAXBContext> resolver = providers.getContextResolver(
      JAXBContext.class, arg3); 
    try { 

     if (resolver != null) { 
      jaxbContext = resolver.getContext(arg0); 
     } 

     if (jaxbContext == null) { 
      jaxbContext = JAXBContext.newInstance(arg0); 

     } 
     type = (T) jaxbContext.createUnmarshaller().unmarshal(arg5); 
     validate(type); 

    } catch (JAXBException e) { 
     throw new WebApplicationException(
       Response.Status.INTERNAL_SERVER_ERROR); 
    } 

    return type; 
} 

protected abstract void validate(T arg0) throws WebApplicationException; 
} 

재정의 validate 메소드 및 @provider와 하위 클래스에 주석을 우리가 완료 : 이것은 내가 블 레즈에서 생각에, 감사 한 일입니다.

+0

안녕하세요, 고마워요. 관련 질문에 대답 해 주시겠습니까? http : //stackoverflow.com/questions/12530155/jax-rs-request-validation-using-xsd-jaxb – adi

+0

나는 뭔가를 놓쳐 야합니다.이 클래스는 실제로 유효성 검사? –

+0

@Deejay 이것은 언젠가 전에 있었고 나는 더 이상 같은 장소에서 일하지 않습니다. 그러나 실제로 추상 클래스는 유효성 검사를 수행하지 않습니다. 단지 형식을 만들고 유효성 검사는 하위 클래스에서 수행됩니다. 분명히 지금 당장은 추상적 인 수퍼 클래스를 조정하여 스키마를 설정하고이를 사용하여 언 마샬링을 수행한다고 상상할 수 있습니다. 이것은 모두 귀하의 필요에 따라 다릅니다. – GWTNewbie

관련 문제