2011-07-28 2 views

답변

18

이것은 아주 좋은 질문입니다!

짧은 대답은 마샬에 setAdapter를 사용 없는 것을/Unmarshaller에 당신이 @XmlJavaTypeAdapter을 사용할 필요가 없습니다 것을 의미하지 않는다이다.

가설 (아직 유효한!) 시나리오로 설명해 드리겠습니다.

웹 응용 프로그램에서 고려, 하나의 스키마 다음 XML을 갖는 형태로 이벤트를 가져옵니다 : 이제

@XmlRootElement(name="event") 
@XmlType(name="") 
public class Event { 

    @XmlElement(required=true) 
    protected String performedBy; 
} 

응용 프로그램이에

<xs:element name="event" > 
    <xs:complexType> 
     <xs:sequence> 
      <!-- Avoiding other elements for concentrating on our adapter --> 
      <xs:element name="performedBy" type="xs:string" /> 
     </xs:sequence> 
    </xs:complexType> 
</xs:element> 

등가, 모델처럼 보일 것이다 이미 사용자에 관한 정보를 유지하는 User이라는 빈을 가지고있다. 이 User이 당신의 JAXB 컨텍스트에 알려지지 않은 것을

public class User { 

    private String id; 
    private String firstName; 
    private String lastName; 

    .. 
} 

참고. 간단히하기 위해 사용자는 POJO로 설정되어 있지만 유효한 Java 클래스가 될 수 있습니다. 응용 프로그램 설계자가 원하는 무엇

이다 User 은 자세한 내용을 얻을으로의 performedBy가 표현되어야 Event. @XmlJavaTypeAdapter이

있다 JAXBContext가 xs:string으로 performedBy에 대한 인식 그림으로 오는 곳 여기

이지만, 자바에서 메모리에 User로 표현되어야한다.

@XmlRootElement(name="event") 
@XmlType(name="") 
public class Event { 

    @XmlElement(required=true) 
    @XmlJavaTypeAdapter(UserAdapter.class) 
    protected User performedBy; 
} 

UserAdapter :

수정 된 모델처럼 보인다.자바 :

public class UserAdapter extends XmlAdapter<String, User> { 

    public String marshal(User boundType) throws Exception { 
      .. 
    } 

    public User unmarshal(String valueType) throws Exception { 
      .. 
    } 
} 

어댑터의 정의는 말한다 -

  1. BoundType이 (Memeory 표현에서) 사용자
  2. 치 형이 String의이 (데이터 유형 JAXB 컨텍스트가 알고있다)이다

다시 질문하기 -

다소 중복되었습니다.

현재 SomeMarshaller.setAdapter (...)는 아무 것도하지 않는 것 같습니다.

마샬링/언 마샬링을 성공적으로 수행하려면 어댑터에 UserContext라는 클래스가 필요하다고 생각해보십시오.

public class UserAdapter extends XmlAdapter<String, User> { 

    private UserContext userContext; 

    public String marshal(User boundType) throws Exception { 
      return boundType.getId(); 
    } 

    public User unmarshal(String valueType) throws Exception { 
      return userContext.findUserById(valueType); 
    } 
} 

이제 UserAdapter가 Instace를 어떻게 가져 오나요? 인스턴스화있어 반면 하나가 항상 공급해야 좋은 디자인으로 ..

public class UserAdapter extends XmlAdapter<String, User> { 

    private UserContext userContext; 

    public UserAdapter(UserContext userContext) { 
     this.userContext = userContext; 
    } 

    public String marshal(User boundType) throws Exception { 
      return boundType.getId(); 
    } 

    public User unmarshal(String valueType) throws Exception { 
      return userContext.findUserById(valueType); 
    } 
} 

그러나 JAXB 런타임은 인자없는 생성자 어댑터를 받아 들일 수 .. 는 (물론 JAXBContext에 응용 프로그램 특정 모델에 대해 알고하지 않습니다)

그래서 고맙게도 옵션이 있습니다 : D

당신은 오히려 자신의 자신에 의해 그것을 복귀하려고보다 UserAdapter의 당신의 unmarshaller 사용하는 지정된 인스턴스를 알 수 있습니다.

public class Test { 

public static void main(String... args) { 
    JAXBContext context = JAXBContext.getInstance(Event.class); 
    Unmarshaller unmarshaller = context.createUnmarshaller(); 

     UserContext userContext = null; // fetch it from some where 
     unmarshaller.setAdapter(UserAdapter.class, new UserAdapter(userContext)); 

     Event event = (Event) unmarshaller.unmarshal(..); 
    } 
} 

setAdapter 방법은 모두 Marshaller & Unmarshaller

참고로 볼 수 있습니다 :

마샬에
  1. setAdapter/Unmarshaller에 당신이 @XmlJavaTypeAdapter을 사용하지 않는다는 것을 의미하지 않는다.

    @XmlRootElement(name="event") 
    @XmlType(name="") 
    public class Event { 
    
        @XmlElement(required=true) 
        // @XmlJavaTypeAdapter(UserAdapter.class) 
        protected User performedBy; 
    } 
    

    당신이 JAXB 런타임이 사용자가 & 값 유형이 다른 것을 당신의 바운드 형이라고 단서가 없습니다 생략하면. (사용하는 경우 또는 유효성 검사 실패) 우리는 어댑터가 인수로 요구되는 시나리오, 따라서 사용 setAdapter 방법을 가지고 있지만 u는 잘못된 XML 을 가진

  2. 을 종료합니다 &이기 때문에 그것은 User를 마샬링하려고합니다.

    일부 adavanced 용도가, 심지어 경우에 당신이 인수 없음의 생성자를 기본 않습니다이 경우도있다, 그러나 당신은 정렬 화/비 정렬 화 조작이 사용

    이 어댑터가 데이터로 구성되어있다 어댑터의 인스턴스를 제공 !

+11

을 ** 그래서 짧은 대답은 NO입니다 ** 당신은 @XmlJavaTypeAdapter 주석을 사용하지 않고 (때문에) XmlAdapter를 사용할 수 없습니다. – user1128134

5

당신은 package-info.java "패키지 수준"이라고

를 사용할 수 있습니다.

예 : marshall/unmarshall하려는 클래스와 동일한 패키지에 package-info.java를 넣으십시오.

클래스 mypackage.model.A와 어댑터 CalendarAdapter가 mypackage.adapter에 있다고 가정합니다. 는 포함 mypackage.model에 package-info.java 파일을 선언 :

@XmlJavaTypeAdapters({ 
    @XmlJavaTypeAdapter(value = CalendarAdapter.class, type = Calendar.class) 
}) 
package mypackage.model; 

import java.util.Calendar; 
import mypackage.adapter.CalendarAdapter; 

클래스 A의 Calendar 형의 모든 필드는 정렬 화 또는 CalendarAdapter와 비 정렬 화됩니다.

당신이 유용한 정보를 찾을 수 있습니다 http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html