IllegalAnnotationExceptions while converting object to XML using Jaxb - jaxb

I have a TrainingCalendarWrapper class which have a list which hold TrainingCalendarVO. In my application
I'm setting the details in TrainingCalendarVO and then added to trainingList of TrainingCalendarWrapper
And then converting TrainingCalendarWrapper to XML using Jaxb.
#XmlRootElement
public class TrainingCalendarWrapper implements Serializable
{
public ArrayList<TrainingCalendarVO> trainingList;
Getters & Setters for trainingList
}
1 counts of illegalAnnotationException Class has two properties of the same name "trainingList" for the below line of code
JAXBContext jaxbContext = JAXBContext.newInstance(TrainingCalendarWrapper.class);

If you are annotating the fields (instance variables) then you need to specify #XmlAccessorType(XmlAccessType.FIELD) at the class level. Otherwise you can add the annotation to the get or set methods.
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html

Related

Handling of XML elements with different name but similar structure using JAXB

I have a XML file with elements having different names but similar structure(same attributes and child elements). I want to convert XML file to Java objects. I have used #XmlAnyElement annotation and it gives the element but it is not convertible to the Java object class. Through eclipse debugging I have verified that it is in the form ElementNSImpl which cannot be cast to the Object class.
Sample XML structure is following,
<element1 attr1="" attr2="" attr3="">
<childElement1>
<childElement2>
</element1>
<element2 attr1="" attr2="" attr3="">
<childElement1>
<childElement2>
</element2>
I am using JAXB annotations.
Root
In JAXB Java classes correspond to complex types in XML Schema. If element1 and element2 have the same type then they refer to the same class.
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private Element element1;
private Element element2;
}
Element
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class Element {
#XmlAttribute
private String attr1;
#XmlAttribute
private String attr2;
#XmlAttribute
private String attr3;
private String childElement1;
private String childElement2;
}

Different name for a generated XSD attribute from that of the java object

Is it possible to generate a XSD from Java object with a name different that of the class or its attribute ? Say I have a class having an attribute "currency" and in the generated xsd i want to rename it as "currencyType"?
Many of the JAXB (JSR-222) annotations (i.e. #XmlElement, #XmlAttribute, #XmlType, etc) enable you to specify a name to override the default one derived from the class or property name.
#XmlElement(name="currencyType")
public String getCurrency() {
return currency;
}

Dependency injection in abstract and concrete classes

I'm using JSF and am running in a problem for quite awhile, I've searched at a lot of places but couldn't find any suitable answer.
Can I have dependency injection working in an abstract (or more generally a class higher in the hierarchy) class ?
Also, how should we handle annotations when working with inheritance ? I've read that the common practice would be not to annotate the abstract class, only the concrete one, but then, it would imply no injection for that abstract ?
My problem is that one (check the last comment) :
Abstract class
#ManagedBean
#ViewScoped
public abstract class AbstractController<T extends VersionedObject> implements Serializable {
#ManagedProperty("#{libraryVersionController}")
private LibraryVersionController libraryVersionController;
public List<T> loadFromDatasource(IVersionedServiceBase<T> service) {
log.info("Loading generic VO from data source");
VersionedObjectFilter filter = new VersionedObjectFilter();
filter.setSelectedLibVersion(libraryVersionController.getSelectedItem());
// etc
}
// getters, setters...
}
Concrete class
#ManagedBean
#ViewScoped
public class DomainController extends AbstractController<Domain> implements Serializable {
private List<Domain> allItems;
private Domain[] selectedItem;
#ManagedProperty(value = "#{domainService}")
private DomainService domainService;
#PostConstruct
public void loadFromDatasource() {
allItems = super.loadFromDatasource(domainService);
// !! DOES NOT WORK, null pointer exception on abstract class (libraryVersionController)
// etc
}
Getters and setters are correctly set up, as I could read in my .xhml it is the concrete class that I'm referencing (#{domainController.allItems}), there is only one #PostConstruct. I'm using JSF2.1 and Mojarra.
Thanks for your help !
As to your NullPointerException, my guess is that AbstractController.setLibraryVersionController is missing. As I understand it, when the AbstractController is constructed (presumably it has an implicit constructor even though it's abstract), that method is needed to fill in the appropriate value.
I know you said all getters and setters are there, but this one seems tricky, so possibly you missed it. If you add logging to this method, you can check that JSF is attempting to fill in the value, and also check whether the value is null or not.
On the general question of how dependency injection works with the inheritance hierarchy, I would guess that your approach is OK, and that dependencies are injected for the base class and then for the derived class, down the chain.

XmlSeeAlso and XmlRootElement names?

In the reference JAXB implementation is there anyway to get XmlSeeAlso to use the name= value from XmlRootElement?
The effect I want is for the type attribute to use the name= value rather than actual class name from XmlSeeAlso.
Is this possible is some other JAXB implementation?
Small example:
#XmlRootElement(name="some_item")
public class SomeItem{...}
#XmlSeeAlso({SomeItem.class})
public class Resource {...}
XML:
<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="some_item">
...
</resource>
Possible without a lot of effort?
About #XmlSeeAlso
The purpose of the #XmlSeeAlso annotation is just to let your JAXB (JSR-222) implementation know that when it is processing the metadata for Resource that it should also process the metadata for the SomeItem class. Some people mistakenly believe that it is related to mapping inheritance since that is the use case it is most often used with. Since the subclasses of a class can not be determined using Java reflection, #XmlSeeAlso is used to let the JAXB implementation know that mappings for the subclasses should also be created.
Below is an example of how you could support your use case:
Resource
The complex type name corresponding to a Java class is supplied via the #XmlType annotation.
package forum12288631;
import javax.xml.bind.annotation.XmlType;
#XmlType(name="some_item")
public class Resource {
}
Demo
The root element name can come from the #XmlRootElement annotation or can be supplied via an instance of JAXBElement. We will create an instance of JAXBElement and indicate that it is holding onto an instance of Object. When marshalled this will for the xsi:type attribute to be included in the output.
package forum12288631;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Resource.class);
Resource resource = new Resource();
JAXBElement<Object> jaxbElement = new JAXBElement<Object>(QName.valueOf("resource"), Object.class, resource);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(jaxbElement, System.out);
}
}
Output
The resulting XML has the root element supplied by the JAXBElement and the value of the xsi:type attribute comes from the #XmlType annotation on Resource.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="some_item"/>

How do I use JAXB #XmlValue on a subclass?

I want XML like this:
<simple>Foo</simple>
I can do this successfully via a JAXB class that looks like this:
#XmlRootElement(name="simple")
class Simple {
#XmlValue
public String contents;
}
But now I need to make the Simple class be a subclass of another class like so:
#XmlRootElement(name="simple")
class Simple extends OtherClass {
#XmlValue
public String contents;
}
That fails with #XmlValue is not allowed on a class that derives another class. I can't easily refactor the superclass away (because of the way we're using #XmlElementRef on a wrapper class). Is there a workaround that will let me annotate my subclass to generate that simple XML?
The accepted answer didn't work for me.
Everything is fine as described but I also needed to add the #XmlTransient to the superclass
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
This use case is supported by MOXy, and IMHO should be supported by the JAXB RI as well:
Simple
This class has a field mapped with #XmlValue and extends OtherClass:
package forum809827;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
#XmlRootElement(name="simple")
class Simple extends OtherClass {
#XmlValue
// #XmlValueExtension
// As of moxy 2.6, XmlValueExtension needs to be added for this to work
public String contents;
}
OtherClass
This is the super class. In MOXy the subclass can map a field/property with #XmlValue as long as the super class does not have any mappings to an XML element:
package forum809827;
import javax.xml.bind.annotation.XmlAttribute;
public class OtherClass {
#XmlAttribute
public String other;
}
Demo
package forum809827;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Simple.class);
Simple simple = new Simple();
simple.contents = "FOO";
simple.other = "BAR";
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(simple, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<simple xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" other="BAR">FOO</simple>
For More Information on Specifying MOXy as Your JAXB Provider
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
I was able to make this work by changing #XmlValue to #XmlMixed and changing the variable to a list. The resulting class should look like the following.
#XmlRootElement(name="simple")
class Simple extends OtherClass {
#XmlMixed
public List<String> contents;
}
This problem happened to me , and took me a little bit time.
Thanks to Blaise Doughan
I go through his blog and find the answer
you have to add a
jaxb.properties file with javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
in the same package in order to use MOXy
add moxy to your maven dependency or add moxy jar
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.5.0</version>
</dependency>
then all set
I have sample here you can go though my project and take a look at
https://github.com/cicidi/HelloCCD/tree/master/Jaxb

Resources