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]
사실
더
classses는 @XmlRootElement 주석, 그래서 내가 잘못된 일을 할 수 없다? xjc (JAXB 2.1)를 fpml-main-4-5.xsd를 가리키고 있으며 모든 유형을 포함합니다.
JAXB XJC가 다른 사람들이 이미 언급하거나 암시 한 내용을 함께 묶기
@XmlRootElement
위해 생성 된 클래스에 주석을 넣을지 여부를 결정하는 규칙 은 간단하지 않습니다 (
).
@XmlRootElement
JAXB 런타임은 특정 오브젝트, 특히 XML 요소 이름 및 네임 스페이스를 마샬링 / 마샬링 해제하기 위해 특정 정보가 필요하기 때문에 존재합니다. 당신은 단지 마샬 러에게 오래된 물건을 전달할 수 없습니다.
@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의 다른 곳에서 사용될 수 있기 때문입니다. 익명 유형으로 시도하십시오.
<xsd:element name="myRootElement" type="MyRootElementType" />
<xsd:complexType name="MyRootElementType">
...
</xsd:complexType>
너도 아마:
<xsd:element name="myRootElement">
<xsd:complexType>
...
<xsd:complexType>
</xsd:element>
비 정렬 화에는 @XmlRootElement가 필요하지 않습니다-Unmarshaller # unmarshall의 2 매개 변수 형식을 사용하는 경우.따라서 대신하는 경우 :
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)이 나를 위해 그것을합니다. JAXBElement를 마샬링하는 경우 @XmlRootElement 주석이 없으면 아무 문제가 없습니다. 나를 혼란스럽게 한 것은 생성 된 ObjectFactory에는 2 개의 createMyRootElement 메소드가 있다는 것입니다. 첫 번째는 매개 변수를 사용하지 않고 래핑되지 않은 객체를 제공하고 두 번째는 래핑되지 않은 객체를 가져 와서 JAXBElement에 래핑하고 JAXBElement가 올바르게 작동하도록 정렬합니다. 여기에 대부분에서 cribbed 사용되는 기본 코드 I (코드는이 회신에서 제대로 포맷되지 않았습니다의 사과 그래서 만약 내가이 새로운 해요)의
:
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>
Here is the binding.xjb
file content
<?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>
As you know the answer is to use the ObjectFactory(). Here is a sample of the code that worked for me :)
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();
}
It's not working for us either. But we did find a widely-quoted article that adds SOME background... I'll link to it here for the sake of the next person: http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html
In case my experience of this problem gives someone a Eureka! moment.. I'll add the following:
I was also getting this problem, when using an xsd file that I had generated using IntelliJ's "Generate xsd from Instance document" menu option.
When I accepted all the defaults of this tool, it generated an xsd file that when used with jaxb, generated java files with no @XmlRootElement
. At runtime when I tried to marshal I got the same exception as discussed in this question.
I went back to the IntellJ tool, and saw the default option in the "Desgin Type" drop down (which of course I didn't understand.. and still don't if I'm honest) was:
Desgin Type:
"local elements/Global complex types"
I changed this to
"local elements/types"
, now it generated a (substantially) different xsd, that produced the @XmlRootElement
when used with jaxb. Can't say I understand the in's and out's of it, but it worked for me.
With a Maven build, you can add the @XmlRootElement
annotation
with the "jaxb2-basics-annotate
" plug-in.
See more information : see
Configure Maven to generate classes from XML Schema using JAXB
Did you try to change your xsd like this?
<!-- create-logical-system -->
<xs:element name="methodCall">
<xs:complexType>
...
</xs:complexType>
</xs:element>
JAXBElement wrappers works for cases where no @XmlRootElement
is generated by JAXB. These wrappers are available in ObjectFactory
class generated by maven-jaxb2-plugin
. For eg:
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;
}
}
After sruggling for two days I found the solution for the problem.You can use the ObjectFactory class to workaround for the classes which doesn't have the @XmlRootElement. ObjectFactory has overloaded methods to wrap it around the JAXBElement.
Method:1 does the simple creation of the object.
Method:2 will wrap the object with @JAXBElement.
Always use Method:2 to avoid javax.xml.bind.MarshalException - with linked exception missing an @XmlRootElement annotation.
Please find the sample code below
Method:1 does the simple creation of the object
public GetCountry createGetCountry() {
return new GetCountry();
}
Method:2 will wrap the object with @JAXBElement.
@XmlElementDecl(namespace = "my/name/space", name = "getCountry")
public JAXBElement<GetCountry> createGetCountry(GetCountry value) {
return new JAXBElement<GetCountry>(_GetCountry_QNAME, GetCountry.class, null, value);
}
Working code sample:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
WebServiceTemplate springWSTemplate = context.getBean(WebServiceTemplate.class);
GetCountry request = new GetCountry();
request.setGuid("test_guid");
JAXBElement<GetCountryResponse> jaxbResponse = (JAXBElement<GetCountryResponse>)springWSTemplate .marshalSendAndReceive(new ObjectFactory().createGetCountry(request));
GetCountryResponse response = jaxbResponse.getValue();
To soluction it you should configure a xml binding before to compile with wsimport, setting generateElementProperty as 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>
참고URL : https://stackoverflow.com/questions/819720/no-xmlrootelement-generated-by-jaxb
'programing' 카테고리의 다른 글
AWS EC2 인스턴스를 핑할 수 없습니다 (0) | 2020.05.09 |
---|---|
파이썬에서 버전 번호를 어떻게 비교합니까? (0) | 2020.05.09 |
MySQL의 유형 : BigInt (20) vs Int (20) (0) | 2020.05.09 |
Rails 4 진품 토큰 (0) | 2020.05.09 |
C #에서 Json 파일 읽기 및 구문 분석 (0) | 2020.05.09 |