I am getting a strange error during unmarshalling.
This is my unmarshal code
File file = new File("resources/test.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(FuzzyControllerType.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
FuzzyControllerType fct=(FuzzyControllerType) jaxbUnmarshaller.unmarshal(file);
This is the error I get:
javax.xml.bind.UnmarshalException: unexpected element
(uri:"", local:"FuzzyController"). Expected elements are <{}fuzzyControllerType>
This is my xml
<?xml version="1.0" encoding="UTF-8"?>
<FuzzyController>
<KnowledgeBase>
<FuzzyVariable name="food" domainleft="0.0" domainright="10.0" scale="" type="input">
<FuzzyTerm name="delicious" complement="false">
<LeftLinearShape Param1="5.5" Param2="10.0"/>
</FuzzyTerm>
<FuzzyTerm name="rancid" complement="false">
<TriangularShape Param1="0.0" Param2="2.0" Param3="5.5"/>
</FuzzyTerm>
</FuzzyVariable>
</KnowledgeBase>
</FuzzyController>
My Fuzzy controller type class looks like this:
package testfuzzy;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "FuzzyControllerType", propOrder = {
"knowledgeBase"
})
#XmlRootElement(name="FuzzyControllerType")
public class FuzzyControllerType {
#XmlElement(name = "KnowledgeBase", required = true)
protected KnowledgeBaseType knowledgeBase;
public KnowledgeBaseType getKnowledgeBase() {
return knowledgeBase;
}
public void setKnowledgeBase(KnowledgeBaseType value) {
this.knowledgeBase = value;
}
}
I haven't used any name spaces. How do I fix this?
It looks like your XML document has the root element "FuzzyController"
Add the annotation #XmlRootElement(name="FuzzyController") to the class.
Hope it will help you.
UPDATE:
Change your code like this
package testfuzzy;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "FuzzyController", propOrder = {
"knowledgeBase"
})
#XmlRootElement(name="FuzzyController")
public class FuzzyController {
#XmlElement(name = "KnowledgeBase", required = true)
protected KnowledgeBaseType knowledgeBase;
public KnowledgeBaseType getKnowledgeBase() {
return knowledgeBase;
}
public void setKnowledgeBase(KnowledgeBaseType value) {
this.knowledgeBase = value;
}
}
Related
I would like to customize idrefs values and prepend a "#", like this simple example, where the friends attribute contains idrefs to Animal or Person elements.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<Animal friends="#id1 #id2" id="id0"/>
<Animal friends="#id0" id="id1"/>
<Person friends="#id0" id="id2"/>
</root>
With Jaxb basic id/idref annotations I get this result (see my code below):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<Animal friends="id1 id2" id="id0"/>
<Animal friends="id0" id="id1"/>
<Person friends="id0" id="id2"/>
</root>
Is there a way to customize how the idref values are marshalled/unmarshalled?
My code
Test Class
package so;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Test {
public static void main (String [] args) {
Root r = new Root();
Animal foo = new Animal("id0");
Animal bar = new Animal("id1");
Person gaz = new Person("id2");
foo.addFriend(bar);
foo.addFriend(gaz);
bar.addFriend(foo);
gaz.addFriend(foo);
r.addMember(foo);
r.addMember(bar);
r.addMember(gaz);
try {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.marshal(r, System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Root.class
package so;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
#XmlElements
({
#XmlElement(name = "Animal", type = Animal.class, required = false),
#XmlElement(name = "Person", type = Person.class, required = false)
})
private List<Friend> members;
public void addMember(Friend f) {
members.add(f);
}
public Root() {
members = new ArrayList<Friend>();
}
}
Person.class
package so;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlIDREF;
#XmlAccessorType(XmlAccessType.FIELD)
public class Person extends Friend {
#XmlAttribute
#XmlIDREF
private List<Friend> friends;
public Person(String id) {
super(id);
friends = new ArrayList<Friend>();
}
public void addFriend(Friend f) {
friends.add(f);
}
}
Animal class
package so;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlIDREF;
#XmlAccessorType(XmlAccessType.FIELD)
public class Person extends Friend {
#XmlAttribute
#XmlIDREF
private List<Friend> friends;
public Person(String id) {
super(id);
friends = new ArrayList<Friend>();
}
public void addFriend(Friend f) {
friends.add(f);
}
}
Friend class
package so;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlSeeAlso;
#XmlSeeAlso({Person.class, Animal.class})
#XmlAccessorType(XmlAccessType.FIELD)
public class Friend {
#XmlAttribute
#XmlID
private String id;
public Friend(String id) {
super();
this.id = id;
}
}
I'm new to spring boot and I'm trying to consume a Soap service from here
using spring boot somehow my code doesn't seem to work. I have generated classes from that wsdl which were saved in my generated-sources folder. How can I consume a remote wsdl properly?
Generated classes folder
Generated classes code
package net.webservicex;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"fromCurrency",
"toCurrency"
})
#XmlRootElement(name = "ConversionRate")
public class ConversionRate {
#XmlElement(name = "FromCurrency", required = true)
#XmlSchemaType(name = "string")
protected Currency fromCurrency;
#XmlElement(name = "ToCurrency", required = true)
#XmlSchemaType(name = "string")
protected Currency toCurrency;
public Currency getFromCurrency() {
return fromCurrency;
}
public void setFromCurrency(Currency value) {
this.fromCurrency = value;
}
public Currency getToCurrency() {
return toCurrency;
}
public void setToCurrency(Currency value) {
this.toCurrency = value;
}
}
ConversionRateResponse.java
package net.webservicex;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"conversionRateResult"
})
#XmlRootElement(name = "ConversionRateResponse")
public class ConversionRateResponse {
#XmlElement(name = "ConversionRateResult")
protected double conversionRateResult;
public double getConversionRateResult() {
return conversionRateResult;
}
public void setConversionRateResult(double value) {
this.conversionRateResult = value;
}
}
Country.java
package net.webservicex;
import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlType;
#XmlType(name = "Currency")
#XmlEnum
public enum Currency {
AFA,
ALL,
DZD,
ARS,
USD,
TRY;
/*Removed some country codes*/
public String value() {
return name();
}
public static Currency fromValue(String v) {
return valueOf(v);
}
}
ObjectFactory.java
package net.webservicex;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
private final static QName _Double_QNAME = new QName("http://www.webserviceX.NET/", "double");
public ObjectFactory() {
}
public ConversionRate createConversionRate() {
return new ConversionRate();
}
public ConversionRateResponse createConversionRateResponse() {
return new ConversionRateResponse();
}
#XmlElementDecl(namespace = "http://www.webserviceX.NET/", name = "double")
public JAXBElement<Double> createDouble(Double value) {
return new JAXBElement<Double>(_Double_QNAME, Double.class, null, value);
}
}
And I'm calling the service from here, somehow this doesn't work.
package com.wsdl;
import net.webservicex.ConversionRate;
import net.webservicex.ConversionRateResponse;
import net.webservicex.Currency;
import net.webservicex.ObjectFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by tenten on 2017/02/15.
*/
#RestController
public class Testing {
#RequestMapping("/ConversionRate")
public double conversionRate() {
ObjectFactory objectFactory = new ObjectFactory();
ConversionRate conversionRate = objectFactory.createConversionRate();
ConversionRateResponse conversionRateResponse = objectFactory.createConversionRateResponse();
Currency usd = Currency.USD;
usd.value();
Currency btn = Currency.BTN;
btn.value();
conversionRate.setToCurrency(usd);
conversionRate.setFromCurrency(btn);
conversionRateResponse.setConversionRateResult(12.00);
return conversionRateResponse.getConversionRateResult();
}
}
i am getting the following while reading from my .xml file.here is the error
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.dJohn.com/teacher", local:"teacher"). Expected elements are (none)
And here is my file.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Teacher xmlns="http://www.dJohn.com/teacher" Id="0001" />
main class
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class convertorDemo {
public static void main(String[] args) {
try {
File file = new File("C:\\file.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Teacher.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Teacher mrS= (Teacher ) jaxbUnmarshaller.unmarshal(file);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
and here is Teacher.java..leaving some other details
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Teacher", propOrder = {
})
public class Teacher{
#XmlAttribute(name = "Id")
protected String Id;
public String getId() {
return Id;
}
public void setId(String value) {
this.Id = value;
}
}
I don't know what my problem is and i am new to JAXB.please help!!
Annotate your Tana class with XmlRootElement.
I have the following annotation using javax.xml.bind.annotation.XmlElement:
#XmlElement
public List<String> getKeywords() {
return keywords;
}
Which produces the following XML when I marshall some example content:
<keywords>keyword1</keywords>
<keywords>keyword2</keywords>
I would like to get the following XML:
<keywords>
<keyword>keyword1</keyword>
<keyword>keyword2</keyword>
</keywords>
What kind of an annotation should I use?
I've tried
#XmlElementWrapper
#XmlElement(name="keyword")
But then the whole content disappears and the result is:
<keywords/>
The same happens also if I only try to rename the element:
#XmlElement(name="keyword")
What am I doing wrong?
UPDATE:
Here is the updated full code for the class according to the first answers, but it is still not working (the result is an empty list <keywords/> when marshalled to XML):
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Content {
private List<String> keywords;
public Content() {}
#XmlElementWrapper(name="keywords")
#XmlElement(name="keyword")
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
I also tried the following with the same result:
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Content {
#XmlElementWrapper(name="keywords")
#XmlElement(name="keyword")
private List<String> keywords;
public Content() {}
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
However, the keywords are not empty as the following produces <keywords>keyword1</keywords><keywords>keyword2</keywords> instead of an empty list:
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Content {
private List<String> keywords;
public Content() {}
#XmlElement
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
The code for marshalling is (JAX-RS):
import java.io.StringWriter;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
#Path("process")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_XML)
public class ContentHandler {
#POST
public Response process(Content content) {
StringWriter stringWriter = new StringWriter();
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Content.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(content, stringWriter);
} catch (JAXBException e) {
return Response.serverError().entity(e.getMessage()).build();
}
return Response.ok(stringWriter.toString(), MediaType.APPLICATION_XML).build();
}
}
You need to leverage #XmlElementWrapper and #XmlElement.
Java Model
Content
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
public class Content {
private List<String> keywords;
public Content() {}
#XmlElementWrapper
#XmlElement(name="keyword")
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
Demo Code
Demo
import java.util.*;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Content.class);
List<String> strings = new ArrayList<String>(2);
strings.add("foo");
strings.add("bar");
Content content = new Content();
content.setKeywords(strings);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(content, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<content>
<keywords>
<keyword>foo</keyword>
<keyword>bar</keyword>
</keywords>
</content>
For More Information
Below are links to a couple articles from my blog that provide additional information:
http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html
http://blog.bdoughan.com/2012/12/jaxb-representing-null-and-empty.html
Use this form:
#XmlElementWrapper(name="keywords")
#XmlElement(name="keyword")
Please note that if keywords is empty then you will get <keywords />.
Sometimes you will need to add #XmlRootElement to your class (depends on the context) and the #XmlAccessorType(XmlAccessType.?) annotation. I usually use #XmlAccessorType(XmlAccessType.FIELD) and annotate my fields with #XmlElement.
Above answer by - Blaise Doughan is completely correct
Another simple way is , even if you don't write the - #XmlElementWrapper
private List<String> keywords;
#XmlElementWrapper
#XmlElement(name="keyword")
public List<String> getKeywords() {
return keywords;
}
You can use it this way - write the XmlAccessorType on Class level , then XML element name will be same as the class member name - keywords
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Content {
private List<String> keywords;
public Content() {}
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
I am trying to parse an xml to java objects, I've read and implemented the following tutorial:
http://www.vogella.com/articles/JAXB/article.html (works perfectly)
But when I create my own clases (similar to those in the tutorial)
I get: Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "clienteList"
Unless I use #XmlAccessorType(XmlAccessType.FIELD) on class Clientes but in the tutorial is not being used.
Any ideas ?
(It works fine with the #XmlAccessorType(XmlAccessType.FIELD) annotation but I want to know why is it being required with my classes while it is not for the classes in the tutorial)
Thank you in advance for any information.
Class Cliente
package mx.com.findep.crediseguros.dto.servicios.finsol;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "cliente")
public class Cliente {
private String numeroPersona;
#XmlElement(name = "numeroPersona")
public String getNumeroPersona() {
return numeroPersona;
}
public void setNumeroPersona(String numeroPersona) {
this.numeroPersona = numeroPersona;
}
}
Class Clientes
package mx.com.findep.crediseguros.dto.servicios.finsol;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "clientes")
//#XmlAccessorType(XmlAccessType.FIELD) //without this line it fails
public class Clientes {
// XmLElementWrapper generates a wrapper element around XML representation
#XmlElementWrapper(name = "clienteList")
// XmlElement sets the name of the entities
#XmlElement(name = "cliente")
private ArrayList<Cliente> clienteList;
public void setClienteList(ArrayList<Cliente> clienteList) {
this.clienteList = clienteList;
}
public ArrayList<Cliente> getClienteList() {
return clienteList;
}
}
Testing My Marshalling
package mx.com.findep.crediseguros.dto.servicios.finsol;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class TestClientesXml {
private static final String SOME_XML = "C:/bea/user_projects/domains/DominioDesarrollo/esquemas/calculoCostoSeguroPeticion.xml";
public static void main(String[] args) throws JAXBException, IOException {
ArrayList<Cliente> clienteList = new ArrayList<Cliente>();
Cliente cliente1 = new Cliente();
cliente1.setNumeroPersona("1");
clienteList.add(cliente1);
Cliente cliente2 = new Cliente();
cliente2.setNumeroPersona("2");
clienteList.add(cliente2);
Clientes clientes = new Clientes();
clientes.setClienteList(clienteList);
JAXBContext context = JAXBContext.newInstance(Clientes.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(clientes, System.out);
m.marshal(clientes, new File(SOME_XML));
System.out.println();
System.out.println("Output from our XML File: ");
Unmarshaller um = context.createUnmarshaller();
Clientes clientes2 = (Clientes) um.unmarshal(new FileReader(SOME_XML));
ArrayList<Cliente> list = clientes2.getClienteList();
for (Cliente cliente : list) {
System.out.println("Cliente: " + cliente.getNumeroPersona());
}
}
}
By default JAXB treats public fields and properties as mapped. If you annotate a field it then considers the field and property as mapped causing the conflict. Without #XmlAccessorType(XmlAccessType.FIELD) you should annotate the get or set method.
For More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
So lets say we have:
#XmlRootElement(name = "book")
public class Book {
#XmlElement(name = "book_title")
private String title;
public getTitle(){..}
public setTitle(){...}
}
if we run the code we will have
Exception in thread "main"
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "title"
this problem is related to the following location:
at public java.lang.String com.example.jaxb.Book.getTitle()
at com.example.jaxb.Book
this problem is related to the following location:
at private java.lang.String com.example.jaxb.Book.title
at com.example.jaxb.Book
But if we add the annotation: XmlAccessorType
#XmlRootElement(name = "book")
#XmlAccessorType(XmlAccessType.FIELD)
public class Book {
the error will disappear.
When have class which want to marshall and have 10 fields, I prefer to annotate only fields, not one time the setter then the getter. So use #XmlAccessorType and annotate only the fields.