I have two objects that are in hierarchical relationship. I have the jaxb mapping for setter methods in the child pojo. While loading the xml into pojo I don't have any issues. However, while generating the xml, I see two element entries in the xml for the same attribute in pojo the object - one with the mapping key and the other with actual variable name.
Example:
//parent class
public class Employee {
private String name;
public String getName(){
return this.name;
}
public void setName(String name){
this.name=name;
}
}
//second class
#XmlRootElement(name = "teacher")
public class Teacher extends Employee {
#Override
public String getName(){
return super.getName();
}
#Override
#XmlElement(name ="NAME")
public void setName(String name){
super.setname(name)
}
}
//xml out put I get is
// like this
<teacher>
<name>John Doe<name/>
<NAME>John Doe</NAME>
</teacher>
How do I fix this? I want just the one with the key - NAME
You could do either:
Mark the name property on the Emoloyee class as #XmlTransient.
Mark the Employee class as #XmlTransient to remove it as a mapped class.
Remove the name property from the Teacher class and annotate the one on Employee with your #XmlElement annotation.
Related
I was Using JSF With EJB using RMI and it was working fine i.e. all the entities that were being used at the EJB had a sekelton on the JSF and in the xhtml i could access its field easily
Below is a sample Code
#ManagedBean("abc")
#SessionScoped
public class ABC{
private Customer customer;
public Customer getCustomer(){
return customer;
}
public void setCustomer(Customer customer){
this.customer=customer;
}
}
//Entity Class Customer
Public class Customer implements Serializable{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}
And in the XHTML pages I could use Like:
<input value="#{abc.customer.name}"/>
As you can see above that I am accessing its direct field therefore it can access both the getter and setter automatically
But Now I haved changed to the Webservices using Axis2 client Generation and they have their own generated skeleton of entities of the EJB
below is a sample:
#ManagedBean("abc")
#SessionScoped
public class ABC{
private WebClientStub.Customer customer;
public Customer getCustomer(){
return customer;
}
public void setCustomer(WebClientStub.Customer customer){
this.customer=customer;
}
}
//Entity Class Customer
Public class Customer implements org.apache.axis2.databinding.ADBBean{
protected String localName;
public String getName(){
return localName;
}
public void setName(java.lang.String name){
this.localName=name;
}
}
and In the JSF I can't access the name Like I was accessing it before
<input value="#{abc.customer.localName}"/>
Instead I can only access its getter or Setter, Can any One explain why, or come Up with a solution
The problem was solved, the autogenerated classes had a different Variable name now i.e. 'localName' in my case and therefore I changed this in the JSF input text box as well(as you can see in the question) the error that was coming was that the 'property was not found' against the localName and I thought the auto-generated getter/setter i.e. getName() and setName() were there i renamed them to getLocalName() and setLocalName() then it worked, hence it turned out JSF only lookes for the getter setter and don't care about the property is declared or not.
I use a JAXB marshaller and I would like to add an empty element with a specific attribute. This is a dummy class:
#XmlRootElement(name="observation")
public class Observation {
#XmlAttribute
public static final String classCode = "OBS";
#XmlAttribute
public static final String moodCode = "EVN";
private String data;
#XmlElement
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
This creates the following XML:
<observation classCode="OBS" moodCode="EVN">
<data>fsdfsdfd</data>
</observation>
Is there any way to add a new element with a specific attribute only (no value at all)? E.g.
<observation classCode="OBS" moodCode="EVN">
<templateId root="2.16.840.1.113883.10.20.1.31"/>
<data>fsdfsdfd</data>
</observation>
This should do it:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "TemplateIdType")
public class TemplateIdType {
#XmlAttribute(name = "root")
protected String root;
// getter and setter
}
(And you add an element of this class to Observation.)
In the example code below, Employee class has been specified with JAXB field level access type. For the property dept, however, the access type has been specified at getter method level with #XMLElement annotation.
During marshalling of Organization class, the following exception is thrown -
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "dept"
this problem is related to the following location:
at public java.lang.String com.playground.jaxb.Employee.getDept()
this problem is related to the following location:
at private java.lang.String com.playground.jaxb.Employee.dept
Can you help me understand why this overriding of JAXB accessor type is not working please? Also any solution would be highly appreciated.
Example
Root Element Class
package com.playground.jaxb;
#XMLRootElement(name="organization")
public class Organization {
#XmlElementWrapper(name = "employees")
#XmlElement(name = "employee")
private Set<Employee> employees;
public Organization{}
// Remainder omitted...
}
Employee Class
package com.playground.jaxb;
#XMLAccessorType(XMLAccessType.FIELD)
public class Employee {
private String name;
private String dept;
#XMLElement(name="department")
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public Employee {}
// Remainder omitted...
}
You can re-name getter/setter pair, e.g. getDept() -> getDepartment()
private String dept;
#XmlElement(name="department")
public String getDeptartment() {
return dept;
}
public void setDeptartment(String dept) {
this.dept = dept;
}
but in this case you will have duplicate in XML
<dept>my_dept</dept>
<department>my_dept</department>
Or you can annotate field dept with #XmlTransient annotation, if you want to change access type it.
#XmlTransient
private String dept;
#XmlElement(name="department")
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
In this case, dept field will be ignored and getter/setter pair will be used instead
I have a question. Is there any way to detect duplicate nodes (with different values) in xml file?
If java class looks like this (I've just made this up for sake of simplicity):
#XmlRootElement(name = "PERSON")
#XmlAccessorType(XmlAccessType.FIELD)
public class Person {
#XmlElement(name = "NAME")
private String name;
#XmlElement(name = "SURNAME")
private String surname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
and input .xml file looks like this:
<person>
<name>John</name>
<surname>Smith</surname>
<name>Jack</name>
</person>
After unmarshalling process, value 'John' gets overriden by value 'Jack'.
Is there any way to detect/avoid this?
(So i can throw Exception or log occurence of this duplicate?)
The general solution to this problem is to set your XML schema as an instance of javax.xml.validation.Schema on that Unmarshaller to ensure the XML matches the expected input.
For More Information
http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html
I'm starting with some Java classes that I would like to be able to unmarshall from XML--I'm determining the schema as I go. I would like to use XML similar to the following:
<Person fname="John" lname="Doe">
<bio><foo xmlns="http://proprietary.foo">Blah <bar>blah</bar> blah</foo></bio>
</Person>
I'm hoping to annontate my Java classes similar to the following:
public class Person {
#XmlAttribute
public String fname;
#XmlAttribute
public String lname;
#XmlElement
public ProprietaryFoo bio;
}
I'd like to pass the <foo xmlns="http://proprietary.foo"> element and it's descendants to a compiled factory class which works like this:
FooFactory.getFooFromDomNode(myFooElement) // Returns a private ProprietaryFooImpl as an instance of the public ProprietaryFoo Interface
It seems like I need to create a DomHandler for ProprietaryFoo but I'm not quite able to figure it out (I was getting “com.xyz.ProprietaryFooImpl nor any of its super class is known to this context.") I'm also interested in XmlJavaTypeAdapter I can't figure out how to receive the ValueType as an Element.
Ended up using both an XmlAdapter and a DomHandler along with a simple Wrapper class.
public class FooWrapper {
#XmlAnyElement(FooDomHandler.class)
public ProprietaryFoo foo;
}
public class FooXmlAdapter extends XmlAdapter<FooWrapper, ProprietaryFoo> {
#Override
public ProprietaryFoo unmarshal(FooWrapper w) throws Exception {
return w.foo;
}
#Override
public FooWrapper marshal(ProprietaryFoo f) throws Exception {
FooWrapper fooWrapper = new FooWrapper();
fooWrapper.foo = f;
return fooWrapper;
}
}
/* The vendor also provides a ProprietaryFooResult class that extends SAXResult */
public class FooDomHandler implements DomHandler<ProprietaryFoo, ProprietaryFooResult> {
#Override
public ProprietaryFooResult createUnmarshaller(ValidationEventHandler validationEventHandler) {
return new ProprietaryFooResult();
}
#Override
public ProprietaryFoo getElement(ProprietaryFooResult r) {
return r.getProprietaryFoo();
}
#Override
public Source marshal(ProprietaryFoo f, ValidationEventHandler validationEventHandler) {
return f.asSaxSource();
}
}
For whatever reason, this didn't work with the standard classes from the com.sun namespace but MOXy handles it well.