문제

FPML (Finanial Products Markup Language) 버전 4.5에서 Java 클래스를 생성하려고합니다. 많은 코드가 생성되지만 사용할 수는 없습니다. 간단한 문서를 직렬화하려고 시도합니다.

javax.xml.bind.MarshalException
  - with linked exception: [com.sun.istack.SAXException2: unable
  to marshal type
  "org.fpml._2008.fpml_4_5.PositionReport"
  as an element because it is missing an
  @XmlRootElement annotation]

사실로 아니요 클래스는 @xmlrootelement 주석이 있으므로 어떻게해야합니까?. XJC (JAXB 2.1)를 FPML-Main-4-5.XSD로 가리키고 있으며 모든 유형을 포함합니다.

도움이 되었습니까?

해결책

다른 사람들이 이미 언급하거나 힌트 한 내용을 함께 묶기 위해 JaxB XJC가 배치 할 것인지 아닌지 결정하는 규칙 @XmlRootElement 생성 된 클래스의 주석은 사소하지 않습니다 (이 기사를 참조하십시오).

@XmlRootElement JAXB 런타임에는 주어진 객체, 특히 XML 요소 이름 및 네임 스페이스를 마샬링/unmarshal로 만들기 위해 특정 정보가 필요하기 때문에 존재합니다. 오래된 물건을 마샬러에게 전달할 수는 없습니다. @XmlRootElement 이 정보를 제공합니다.

주석은 편의성 일뿐입니다. JaxB는 그것을 요구하지 않습니다. 대안은 사용하는 것입니다 JAXBElement 동일한 정보를 제공하는 래퍼 객체 @XmlRootElement, 그러나 주석이 아닌 대상의 형태로.

하지만, JAXBElement XML 요소 이름과 네임 스페이스를 알아야하기 때문에 객체는 구조적으로 어색합니다.

고맙게도 XJC가 클래스 모델을 생성하면 ObjectFactory. 이것은 부분적으로 JAXB V1과의 거꾸로 호환성을위한 것이지만 XJC가 생성 된 생성 된 공장 방법을 넣을 수있는 장소로도 있습니다. JAXBElement 자신의 물체 주위에 포장기. XML 이름과 네임 스페이스를 처리하므로 걱정할 필요가 없습니다. 당신은 그냥 살펴보아야합니다 ObjectFactory 필요한 방법을 찾기 위해 방법 (및 큰 스키마가 수백 개가있을 수 있음).

다른 팁

이것은 이미 위에 링크 된 블로그 게시물의 맨 아래에 언급되어 있지만 이것은 나에게 대접처럼 작동합니다.

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(new JAXBElement<MyClass>(new QName("uri","local"), MyClass.class, myClassInstance), System.out);

위의 답변 중 하나에서 암시 된 바와 같이, XSD에서 유형이 명명 된 유형으로 정의되면 루트 요소에 xmlRootElement가 표시되지 않습니다. XSD의 다른 곳에서는 이름이 지정된 유형을 사용할 수 있기 때문입니다. 익명 유형 (즉, 즉 : 대신 : mking) 시도하십시오.

<xsd:element name="myRootElement" type="MyRootElementType" />

<xsd:complexType name="MyRootElementType">
...
</xsd:complexType>

너도 아마:

<xsd:element name="myRootElement">
    <xsd:complexType>
    ...
    <xsd:complexType>
</xsd:element>

@xmlRootElement는 UNMARSHALLING에 필요하지 않습니다.

따라서 수행하는 대신 :

UserType user = (UserType) unmarshaller.unmarshal(new StringReader(responseString));

하나는해야합니다 :

JAXBElement<UserType> userElement = unmarshaller.unmarshal(someSource, UserType.class);
UserType user = userElement.getValue();

후자의 코드는 userType 클래스 수준에서 @xmlRootElement 주석이 필요하지 않습니다.

Joe의 대답 (Joe Jun 26 '09 at 17:26)이 저를 위해 그렇게합니다. 간단한 대답은 @xmlrootelement 주석이 없다는 것이 Jaxbelement를 마샬링하면 아무런 문제가 없다는 것입니다. 저를 혼란스럽게 한 것은 생성 된 ObjectFactory가 2 개의 createmyrootelement 방법을 가지고 있다는 것입니다. 첫 번째는 매개 변수를 취하지 않고 포장되지 않은 객체를 제공하고, 두 번째는 랩핑되지 않은 물체를 가져 와서 Jaxbelement로 감싸고 Jaxbelement가 잘 작동하는 마샬링을 반환합니다. 여기에 내가 사용한 기본 코드가 있습니다 (저는 이것에 익숙하지 않으므로 코드 가이 답장에서 올바르게 형식화되지 않으면 사과드립니다). 링크 텍스트:

ObjectFactory objFactory = new ObjectFactory();
MyRootElement root = objFactory.createMyRootElement();
...
// Set root properties
...
if (!writeDocument(objFactory.createMyRootElement(root), output)) {
    System.err.println("Failed to marshal XML document");
}
...

private boolean writeDocument(JAXBElement document, OutputStream output) {

  Class<?> clazz = document.getValue().getClass();
  try {
    JAXBContext context =
        JAXBContext.newInstance(clazz.getPackage().getName());
    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    m.marshal(document, output);
    return true;

  } catch (JAXBException e) {
    e.printStackTrace(System.err);
    return false;
  }
}

바인딩을 사용 하여이 문제를 해결할 수 있습니다 XSD의 기본 유형에 대한 @xmlrootelement 클래스를 생성하는 방법은 무엇입니까?.

다음은 Maven의 예입니다

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.3.1</version>
            <executions>
                <execution>
                    <id>xjc</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <schemaDirectory>src/main/resources/xsd</schemaDirectory>
                <packageName>com.mycompany.schemas</packageName>
                <bindingFiles>bindings.xjb</bindingFiles>
                <extension>true</extension>
            </configuration>
        </plugin>

여기에 있습니다 binding.xjb 파일 내용

<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
              xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
              jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <jxb:bindings schemaLocation="path/to/myschema.xsd" node="/xs:schema">
        <jxb:globalBindings>
            <xjc:simple/>
        </jxb:globalBindings>
    </jxb:bindings>
</jxb:bindings>

아시다시피 대답은 ObjectFactory ()를 사용하는 것입니다. 다음은 저를 위해 일한 코드 샘플입니다. :)

ObjectFactory myRootFactory = new ObjectFactory();

MyRootType myRootType = myRootFactory.createMyRootType();

try {

        File file = new File("./file.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(MyRoot.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        //output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        JABXElement<MyRootType> myRootElement = myRootFactory.createMyRoot(myRootType);

        jaxbMarshaller.marshal(myRootElement, file);
        jaxbMarshaller.marshal(myRootElement, System.out);

    } catch (JAXBException e) {
        e.printStackTrace();
    }

그것은 우리를 위해 일하지 않습니다. 그러나 우리는 배경을 추가하는 널리 인용 된 기사를 찾았습니다. 다음 사람을 위해 여기에 연결하겠습니다. http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html

이 문제에 대한 나의 경험이 누군가에게 유레카를 제공하는 경우! 순간 .. 다음을 추가하겠습니다.

또한 Intellij의 "인스턴스 문서에서 XSD 생성"메뉴 옵션을 사용하여 생성 한 XSD 파일을 사용할 때도이 문제가 발생했습니다.

이 도구의 모든 기본값을 수락하면 JAXB와 함께 사용할 때 NO가있는 Java 파일을 생성하는 XSD 파일을 생성했습니다. @XmlRootElement. 마샬을 시도했을 때 런타임 에이 질문에서 논의 된 것과 동일한 예외를 얻었습니다.

나는 Intellj 도구로 돌아가서 "Desgin Type"드롭 다운 (물론 이해하지 못한 것입니다. 그리고 여전히 정직하지 않더라도)에서 기본 옵션을 보았습니다.

Desgin 유형 :

"지역 요소/글로벌 단지 유형"

나는 이것을 변경했다

"로컬 요소/유형"

, 이제는 (실질적으로) 다른 XSD를 생성하여 @XmlRootElement JaxB와 함께 사용될 때. 내가 IN과 아웃을 이해한다고 말할 수는 없지만 그것은 나를 위해 효과가있었습니다.

Maven 빌드를 사용하면 추가 할 수 있습니다 @XmlRootElement 주석

이랑 "jaxb2-basics-annotate" 플러그인.

자세한 내용은 참조하십시오

JAXB를 사용하여 XML 스키마에서 클래스를 생성하도록 Maven 구성

그리고 JAXB XJC 코드 생성

이렇게 XSD를 변경하려고 했습니까?

<!-- create-logical-system -->
<xs:element name="methodCall">
  <xs:complexType>
    ...
  </xs:complexType>
</xs:element>

Jaxbelement 포장지는 아니오의 경우에 작동합니다 @XmlRootElement JAXB에 의해 생성됩니다. 이 래퍼는 사용할 수 있습니다 ObjectFactory 수업에 의해 생성됩니다 maven-jaxb2-plugin. 예를 들어 :

     public class HelloWorldEndpoint {
        @PayloadRoot(namespace = NAMESPACE_URI, localPart = "person")
        @ResponsePayload
        public JAXBElement<Greeting> sayHello(@RequestPayload JAXBElement<Person> request) {

        Person person = request.getValue();

        String greeting = "Hello " + person.getFirstName() + " " + person.getLastName() + "!";

        Greeting greet = new Greeting();
        greet.setGreeting(greeting);

        ObjectFactory factory = new ObjectFactory();
        JAXBElement<Greeting> response = factory.createGreeting(greet);
        return response;
      }
 }

이틀 동안 srugging 후 문제에 대한 해결책을 찾았습니다. ObjectFactory 없는 클래스에 대한 수업에서 해결 방법 @xmlrootelement. ObjectFactory는 Jaxbelement 주위에 랩핑하는 방법을 과부하 시켰습니다. 방법 : 1 대상의 간단한 창조를 수행합니다 방법 : 2 물체를 감싸게됩니다 @jaxbelement. 항상 사용하십시오 방법 : 2 javax.xml.bind.marshalexception을 피하려면 링크 된 예외가있는 @xmlrootelement 주석이 없습니다.

방법 : 1

public GetCountry createGetCountry() {
        return new GetCountry();
    }

방법 : 2

 @XmlElementDecl(namespace = "my/name/space", name = "getCountry")
 public JAXBElement<GetCountry> createGetCountry(GetCountry value) {
        return new JAXBElement<GetCountry>(_GetCountry_QNAME, GetCountry.class, null, value);
    }

작업 코드 샘플 :

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
WebServiceTemplate springWSTemplate = context.getBean(WebServiceTemplate.class);

GetCountry request = new GetCountry();
request.setGuid("1f3e1771-3049-49f5-95e6-dc3732c3227b");

JAXBElement<GetCountryResponse> jaxbResponse = (JAXBElement<GetCountryResponse>)springWSTemplate .marshalSendAndReceive(new ObjectFactory().createGetCountry(request));

GetCountryResponse response = jaxbResponse.getValue();

해결하려면 wsimport로 컴파일하기 전에 XML 바인딩을 구성하고 GenerateElementProperty를 False로 설정해야합니다.

     <jaxws:bindings wsdlLocation="LOCATION_OF_WSDL"
      xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
      xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
         <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
    <jaxws:bindings  node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='NAMESPACE_OF_WSDL']">
      <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xjc:generateElementProperty>false</xjc:generateElementProperty> 
      </jxb:globalBindings>
  </jaxws:bindings>
</jaxws:bindings>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top