jaxb에 의해 생성 된 @xmlrootelement 없음
문제
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>