I have following hibernate property:
#Id()
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id = null;
I want to add JAXB annotation #XmlID to this id but #XmlID can only be applied to String data types. How can I solve this problem.
#XmlID
#Transient
public String getXId(){
return this.id;
}
public String setXId(String s){
this.id = Long.parseDouble(s);
}
Use #XmlJavaTypeAdapter(IDAdapter.class) along with #XmlID where IDAdapter is
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class IDAdapter extends XmlAdapter<String, Long> {
#Override
public Long unmarshal(String string) throws Exception {
return DatatypeConverter.parseLong(string);
}
#Override
public String marshal(Long value) throws Exception {
return DatatypeConverter.printLong(value);
}
}
Related
Does XStream handle JAXB #XmlTransient attributes by default? XStream seems to be ignoring the #XmlTransient attribute & serializing the field anyway.
In the sample code below. ExampleClass2 is getting serialized even though I don't want it to be. Further details are that these classes are being populated by OpenJPA.
XStream Code
XStream _x0 =null;
_x = XStreamImpl.getInstance();
_x.toXML(_object)
Class I want to serialize
#DataCache
#Entity
public class ExampleClass implements Serializable {
private short defaultOption;
private int primaryKey;
private short orderId;
#XmlTransient
private ExampleClass2 _exampleClass2;
#XmlTransient
public ExampleClass2 getTblPpwsCommCfgCombo() {
return _exampleClass2;
}
#XmlTransient
public void setExampleClass2(ExampleClass2 _exampleClass2) {
this._exampleClass2 = _exampleClass2;
}
public short getDefaultOption() {
return defaultOption;
}
public void setDefaultOption(short defaultOption) {
this.defaultOption = defaultOption;
}
public short getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(int primaryKey) {
this.primaryKey = primaryKey;
}
public short getOrderId() {
return orderId;
}
public void setOrderId(short orderId) {
this.orderId = orderId;
}
}
You can use the #Transient annotation or transiet key word:
#Transient
private ExampleClass2 _exampleClass2;
~
I have the following inheritance hierarchy defined in java.
public class BaseModel extends HashMap<String, Object> {
public String getString(String key) {
return (String)this.getOrDefault(key, "EMPTY");
}
}
public class Entity extends BaseModel {
private String id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Now in a groovy script I try to do the following:
Entity entity = new Entity();
entity.id = "101";
entity.name = "Apple"
and "id" and "name" are not recognized. The funny thing is they are recognized if I do one of the following:
not inherit Entity from BaseModel
Rather than inherit BaseModel from HashMap, make HashMap a data member of BaseModel
inherit Entity directly from HashMap
At first I thought that groovy is not recognizing the "id" and "name" syntax because of extending HashMap, but #3 above proves that incorrect. I am stumped as to why this is not being recognized at this point. Can someone help me out? It should be easy enough to copy paste this and try it out yourself.
The problem seems to be the setters and getters inside the Entity Class, everything in groovy is public and it creates all the getters and setters methods.
I tested the next code in the groovy console and it worked.
public class BaseModel extends HashMap<String, Object> {
public String getString(String key) {
return (String)this.getOrDefault(key, "EMPTY");
}
}
public class Entity extends BaseModel {
private String id;
private String name;
}
Entity entity = new Entity();
entity.id = "101";
entity.name = "Apple"
println entity.id
It prints 101 in the groovyConsole output screen.
When Entity is extending from BaseModel or directly a HashMap, Entity becomes a Map. So, when we say entity.id, Groovy is trying to find an entry in the map whose key is 'id'. As there is no such entry, it prints out null.
public class Entity extends HashMap<String, String> {
private String id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Entity entity = new Entity();
entity.id = "101";
entity.name = "Apple"
println entity.id //prints null
But when Entity is not extending from BaseModel anymore, entity.id will be interpreted just as a member of Entity.
public class Entity {
private String id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Entity entity = new Entity();
entity.id = "101";
entity.name = "Apple"
println entity.id //prints 101
I am new to jaxb. I have a scenario here I need to generate follwing XML using JAXB
<WCHECK>
<ALIASES>
<ENTRY>
<ENABLED>No</ENABLED>
<TYPE>AKA</TYPE>
<TEXT>AL1 JAMMALI IMAD BEN BECHIR BEN HAMDA</TEXT>
<NATIVE>Yes</NATIVE>
</ENTRY>
<ENTRY>
<ENABLED>Yes</ENABLED>
<TYPE>AKA</TYPE>
<TEXT>AL2 JAMMALI IMAD BEN BECHIR BEN HAMDA</TEXT>
<NATIVE>Yes</NATIVE>
</ENTRY>
</ALIASES>
<PERMUTATIONS>
<ENTRY>
<ENABLED>No</ENABLED>
<TEXT>Jammali Hamda</TEXT>
</ENTRY>
</PERMUTATIONS>
</WCHECKS>
I have created Allias.java and Permussions.java for the same
#Entity
#Table(name="ING_ALIAS")
public class Aliases {
private String id;
private String type;
private String text;
private boolean enabled;
private boolean isNativeAllias;
private VwatchDetails vwatchDetails;
#Id
#Column(name="ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Column(name="KA_TYPE")
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#Column(name="TEXT")
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ENTRY_ID", nullable = false)
public VwatchDetails getVwatchDetails() {
return vwatchDetails;
}
public void setVwatchDetails(VwatchDetails vwatchDetails) {
this.vwatchDetails = vwatchDetails;
}
#Column(name="IS_ENABLED")
public boolean getEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
#Column(name="IS_NATIVE_ALIAS")
public boolean getIsNativeAllias() {
return isNativeAllias;
}
public void setIsNativeAllias(boolean isNativeAllias) {
this.isNativeAllias = isNativeAllias;
}
This class generate xml file but Its missing the ENTRY> tag. I would like to know how can I add ENTRY tag For each record of Allias and Permutations. Kindly assist me on this. Thanks in Advance
You can use the #XmlElementWrapper annotation to add a grouping element. Then use the #XmlElement annotation to control the element name that corresponds to each item in the collection.
#XmlRootElement(name="WCHECK")
#XmlAccessorType(XmlAccessType.FIELD)
public class WCheck
#XmlElementWrapper(name="ALIASES")
#XmlElement(name="ENTRY")
private List<Alias> aliases;
#XmlElementWrapper(name="PERMUTATIONS")
#XmlElement(name="ENTRY")
private List<Permutation> permutations;
}
The below is my JAXB Binding class which i am using during JAXB Unmarshalling process .
package com;
#XmlRootElement(name = "request")
#XmlAccessorType(XmlAccessType.FIELD)
public class CustAcct {
#XmlAttribute
private String cust;
#XmlAttribute
private String acct;
public CustAcct() {
super();
}
public String getCust() {
return cust;
}
public void setCust(String s) {
cust = s;
}
public String getAcct() {
return acct;
}
public void setAcct(String s) {
acct = s;
}
}
Now my question is that , i am unable to include the annotation #Context ServletContext inside the above class .
public class CustAcct {
#XmlAttribute
private String cust;
#XmlAttribute
private String acct;
#Context
ServletContext cont ;
I am getting the Exception , with this Message
javax.servlet.servletcontext is an interface and jaxb can't handle interfaces
Please let me know if is it possible to have the inbuilt ServletContext Annotation inside the JAXB Binding class ??
Thanks in advance .
I tried this way ,
#XmlRootElement(name = "request")
#XmlAccessorType(XmlAccessType.FIELD)
public class CustAcct {
#XmlAttribute
private String acct;
#XmlTransient
#Context
ServletContext con;
public CustAcct() {
super();
}
public String getAcct() {
return acct;
}
public void setAcct(String s) {
acct = s;
}
}
But i am getting the following Exception when i am trying to access it inside a Jersey Service
SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.NullPointerException
You can annotate that field with #XmlTransient. This prevents your JAXB (JSR-222) implementation from treating it as mapped data.
For More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
Here is what I have so far to marshall my POJO using JAXB :
#XmlRootElement
public class Local {
private Entity entity;
public void setEntity(Entity entity) {
this.entity = entity;
}
#XmlElement
public Entity getEntity() {
return entity;
}
}
and
#XmlRootElement
public class Entity {
private String name;
private String comment;
public void setName(String name){
this.name = name;
}
#XmlAttribute
public String getName(){
return this.name;
}
public void setComment...
#XmlAttribute
public void getComment...
}
With that, I get something like this:
<local>
<entity name="" comment=""></entity>
</local>
However, I would prefer to have the name attribute as an attribute of the local:
<local entityName="" entityComment=""></local>
Is the XmlJavaTypeAdapter a good way to begin with?
Thanks,
Alex
There are a couple of different options to handle this use case:
Option #1 - XmlAdapter (Any JAXB implementation)
You could use an XmlAdapter for this use case. This will work as long as only one attribute value comes from the Entity object:
EntityAdapter
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class EntityAdapter extends XmlAdapter<String, Entity>{
#Override
public String marshal(Entity entity) throws Exception {
if(null == entity) {
return null;
}
return entity.getName();
}
#Override
public Entity unmarshal(String name) throws Exception {
Entity entity = new Entity();
entity.setName(name);
return entity;
}
}
Local
The XmlAdapter is linked with the field/property using the #XmlJavaTypeAdapter annotation:
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
public class Local {
private Entity entity;
public void setEntity(Entity entity) {
this.entity = entity;
}
#XmlAttribute
#XmlJavaTypeAdapter(EntityAdapter.class)
public Entity getEntity() {
return entity;
}
}
For More Information
http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html
http://blog.bdoughan.com/2010/12/jaxb-and-immutable-objects.html
Option #2 - #XmlPath (EclipseLink JAXB (MOXy)
Alternatively if you are using EclipseLink JAXB (MOXy), the you could use the #XmlPath extension. This is useful with the Entity object corresponds to multiple XML attributes:
Local
Specifying the XPath "." indicated that the child contents will be written into the parent element
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
#XmlRootElement
public class Local {
private Entity entity;
public void setEntity(Entity entity) {
this.entity = entity;
}
#XmlPath(".")
public Entity getEntity() {
return entity;
}
}
Entity
public class Entity {
private String name;
private String comment;
public void setName(String name){
this.name = name;
}
#XmlAttribute(name="entityName")
public String getName(){
return this.name;
}
public void setComment(String comment){
this.comment = comment;
}
#XmlAttribute(name="entityComment")
public String getComment(){
return this.comment;
}
}
For More Information
http://bdoughan.blogspot.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html
http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html