I have the following class:
#XmlRootElement(name = "any-text")
public class AnyText {
#XmlElementWrapper(name = "fixed-text", required = true)
#XmlElementRefs({
#XmlElementRef(name = "year", namespace = "http://foo.org/", type = JAXBElement.class, required = false),
#XmlElementRef(name = "title", namespace = "http://foo.org/", type = JAXBElement.class, required = false)
})
#XmlMixed
protected List<Serializable> fixedText = new ArrayList<Serializable>();
...
which is supposed to represent the following XML:
<any-text xmlns="http://foo.org/">
<fixed-text>The story <title>Alice in Wonderland</title> was printed in <year>1865</year>.</fixed-text>
</any-text>
However when I unmarshall and marshall this XML, I get this:
<any-text xmlns="http://foo.org/">
<fixed-text>
<title>Alice in Wonderland</title>
<year>1865</year>
</fixed-text>
</any-text>
basically all text nodes are gone. I checked the memory model and found out that they are not unmarshalled. When I try to add text nodes programatically and marshall the model, text nodes still do not appear. Any workaround is appreciated.
I am using JAXB v2.2.4, but I tested also v2.2.8 with no success.
This issue is very similar (perhaps identical) to one described here and I have also reported it as JAXB-1107.
This appears to be a bug in the JAXB implementation.
The work around is to split your JAXB entity class into two.
#XmlRootElement(name = "any-text")
public class AnyText {
#XmlElement(name = "fixed-text", required = true)
protected FixedText fixedText;
...
}
public class FixedText {
#XmlElementRefs({
#XmlElementRef(
name = "year",
namespace = "http://foo.org/",
type = JAXBElement.class,
required = false),
#XmlElementRef(
name = "title",
namespace = "http://foo.org/",
type = JAXBElement.class,
required = false)
})
#XmlMixed
protected List<Serializable> fixedText = new ArrayList<Serializable>();
}
Related
I got class:
public abstract class AbstractEntity {
#Getter
#Column(nullable = false, unique = true, updatable = false)
private UUID uuid = UUID.randomUUID();
}
and test:
def 'should be transitive: if x.equals(y) and y.equals(z) then x.equals(z)'() {
given:
AbstractEntity place = new Place()
AbstractEntity secondPlace = new Place()
AbstractEntity thirdPlace = new Place()
and: 'all entities has same uuid what makes them equal'
secondPlace.changeUuid(place.uuid)
thirdPlace.changeUuid(place.uuid)
line secondPlace.changeUuid(place.uuid) throws exception: groovy.lang.ReadOnlyPropertyException: Cannot set readonly property
How can I set this field value without using java reflection?
You seem to have an attribute in the #Column 'updatable = false. My first reaction is to think that this stops variables from being updated.
There is also no #Setter annotation which could be useful in this scenario.
Then you could use this method within your test.
For starters, I'm creating some routes using Camel ver 2.15 (in Fuse 6.2.1).
In my route, i'm trying to create a XML from a pojo that was generated using cxf-xjc maven plugin (cxf-xjc read some xsd somewhere then from the xsd, the pojos with jaxb annotations were produced).
The pojos are TempProject and TempProjects.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(
name = "",
propOrder = {"ecode", "tempName"}
)
#XmlRootElement(
name = "TempProject"
)
public class TempProject implements Serializable {
#XmlElement(
name = "Ecode",
required = true
)
protected String ecode;
#XmlElement(
name = "TempName",
required = true
)
protected String tempName;
public TempProject() {
}
public String getEcode() {
return this.ecode;
}
public void setEcode(String value) {
this.ecode = value;
}
public String getTempName() {
return this.tempName;
}
public void setTempName(String value) {
this.tempName = value;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(
name = "",
propOrder = {"tempProjects"}
)
#XmlRootElement(
name = "TempProjects"
)
public class TempProjects implements Serializable {
#XmlElement(
name = "TempProject",
required = true
)
protected List<TempProject> tempProjects;
public TempProjects() {
}
public List<TempProject> getTempProjects() {
if (this.tempProjects == null) {
this.tempProjects = new ArrayList();
}
return this.tempProjects;
}
}
I can generate the xml using this code:
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[]{TempProjects.class});
jaxbContext.createMarshaller();
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(jaxbContext); //import org.apache.camel.converter.jaxb.JaxbDataFormat;
I call
.marshal(jaxbDataFormat)
in my route to effect the marshalling from the pojo to xml.
The generated xml is posted below:
<TempProjects xmlns="http://blah.blah/foo/schema/v2">
<TempProject>
<Ecode>1</Ecode>
<TempName>Tempname1</TempName>
</TempProject>
<TempProject>
<Ecode>2</Ecode>
<TempName>Tempname2</TempName>
</TempProject>
How can i generate a marshalled xml that will have a namespace like this...
<TempProjects xmlns:myprefix="http://blah.blah/foo/schema/v2">
Reason being why I needed a namespaceprefix is because I plan to split the values (e.g. Ecode) in the xml using xpath and I needed a namespaceprefix to do that (thats what ive researched, i might be wrong).
My planned code in my route is
.marshal(jaxbDataFormat)
.split( xpath("/TempProjects/TempProject/Ecode/text()").namespaces(ns1),
new ProjectIdsAggregator()) //the above xpath doesn't work because it doesn't have a namespace prefix
//Namespaces ns1 = new Namespaces("myprefix", "http://blah.blah/foo/schema/v2" );
I looked at jaxbDataFormat.setNamespacePrefixRef("myprefix"), but i got an error (org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: myprefix of type: java.util.Map)
I'm actually quite new in the apache camel routing world, so i might be missing some basic stuff.
You don't need to change your XML at all. It is fine.
With the XML you posted and the Namespace declaration you posted, the following XPath works fine to split the XML (as an example) into two TempProject parts:
xpath("/myprefix:TempProjects/myprefix:TempProject").namespaces(ns1)
Because you declared the XML namespace like this:
Namespaces ns1 = new Namespaces("myprefix", "http://blah.blah/foo/schema/v2" )
Your XPath must use the prefix myprefix for all elements:
/myprefix:TempProjects/myprefix:TempProject
I am trying to switch from JAXB RI 2.2.7 to MOXy JAXB 2.5.2 implementation.
I notice the following difference in namespace and prefix in the generated XML output snippet:
JAXB RI:
<xbrli:xbrl xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:bd-algemeen="http://www.nltaxonomie.nl/7.0/basis/bd/items/bd-algemeen" xmlns:iso4217="http://www.xbrl.org/2003/iso4217">
<bd-algemeen:OperatingSystem contextRef="cc_131">W</bd-algemeen:OperatingSystem>
<xbrli:unit id="uu_692">
<xbrli:measure>iso4217:EUR</xbrli:measure>
</xbrli:unit>
</xbrli:xbrl>
MOXy:
<xbrli:xbrl xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:bd-algemeen="http://www.nltaxonomie.nl/7.0/basis/bd/items/bd-algemeen">
<bd-algemeen:OperatingSystem contextRef="cc_131">W</bd-algemeen:OperatingSystem>
<xbrli:unit id="uu_662">
<xbrli:measure xmlns:ns0="http://www.xbrl.org/2003/iso4217">ns0:EUR</xbrli:measure>
</xbrli:unit>
</xbrli:xbrl>
1) How do I configure MOXy to output the same as the RI? The MOXy output is valid but The XML (actually XBRL) document I create must have predefined prefixes.
2) I use a an instance of "com.sun.xml.bind.marshaller.NamespacePrefixMapper" to indicate the prefix that should be used. However MOXy doesn't call this in case of the iso4217 namespace, why (I debugged the MOXy namespace resolver but got a bit lost ;)?
BTW: the prefixMapper is used by Moxy for other namespaces (like the "xbrli"), but not for this iso4217, what is the difference?
I haved added "bd-algemeen", as the prefix mapper is called for the prefix "bd-algemeen". This mapping doesn't use QName as used by iso4217.
3) I tried the #XmlSchema annotation in the pacakage-info.java in the generated iso4217 pacakge, to define the prefix, but no luck, neither do I want to use this as it concerns generated code that is easily overwritten.
The domain object:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = { "divide", "measures" })
#XmlRootElement(name = "unit")
public class Unit {
protected Divide divide;
#XmlElement(name = "measure")
protected List<QName> measures;
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = { "operatingSystem"})
public static class TaxDataBedrijf {
#XmlElement(name = "OperatingSystem", namespace = "http://www.nltaxonomie.nl/7.0/basis/bd/items/bd-algemeen")
protected Astring1ItemType operatingSystem;
The creation of the Unit instance:
final Unit item = new Unit();
item.getMeasures().add(new QName("http://www.xbrl.org/2003/iso4217", "EUR", "iso4217"));
taxData = new TaxDataBedrijf();
taxData.setOperatingSystem(createOperatingSystem(context, 'W'));
I thought it might be because of the QName usage, but this is also directly used in other places and is used correctly. For example, Moxy is able to generate this snippet:
<xbrli:xbrl xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:bd-domains="http://www.nltaxonomie.nl/7.0/basis/bd/domains/bd-domains" xmlns:bd-axes="http://www.nltaxonomie.nl/7.0/domein/bd/axes/bd-axes">
<xbrli:scenario>
<xbrldi:explicitMember dimension="bd-axes:TimeDimension">bd-domains:Current</xbrldi:explicitMember>
</xbrli:scenario>
</xbrli:xbrl>
And the corresponding java binding:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = { "value" })
#XmlRootElement(name = "explicitMember")
public class ExplicitMember {
#XmlValue
protected QName value;
#XmlAttribute(name = "dimension")
protected QName dimension;
}
And it's creation:
final ExplicitMember item = new ExplicitMember();
item.setDimension(new QName("http://www.nltaxonomie.nl/7.0/domein/bd/axes/bd-axes", "TimeDimension"));
item.setValue(new QName("http://www.nltaxonomie.nl/7.0/basis/bd/domains/bd-domains", "Current"));
Please some advice on how to solve this such that I can use MOXy instead of the RI (where to look in the Moxy code maybe?).
The behaviour you are seeing is a bug, I have opened up the following issue for it:
https://bugs.eclipse.org/452713
I got it working with the correct namespace notation, that is, that it generates:
<xbrli:unit id="uu_382">
<xbrli:measure>iso4217:EUR</xbrli:measure>
</xbrli:unit>
I spend some (lot ;) time debugging the Moxy code and comparing the namespaces that were correctly used and discovered that the ObjectFactory for the above snippet doesn't contain any #XmlElementDecl annotation like the ones that were working. When adding this, it works, namely:
private static final QName EUR_QNAME = new QName("http://www.xbrl.org/2003/iso4217", "EUR", "iso4217");
#XmlElementDecl(namespace = "http://www.xbrl.org/2003/iso4217", name = "EUR", substitutionHeadNamespace = "http://www.xbrl.org/2003/instance", substitutionHeadName = "item")
public JAXBElement<EUR> createEURO() {
return new JAXBElement<EUR>(EUR_QNAME, EUR.class, null, createEUR());
}
I noticed that when the Xbrl (root tag) mapping is created, it will loop through the properties, and one of these properties is the property "itemsAndTuplesAndContexts". It then loop through the associated reference elements (Moxy code: MappingGenerator.generateMappingForReferenceProperty(..)) and will add them to it's namespace resolver map with generated prefix, that is stored in it's descriptor.
During marshalling, it will use the prefix mapper to map it's stored namespaces. Because I added #XmlElementDecl declaration for the iso4217 element, it's found a referencing Element, and as such it's added to the namepace resolver map of the Xbrl root element, and as such used during marshalling in the prefix mapper.
A few questions I don't have very clear:
Why is this #XmlElementDecl required in Moxy, and not by the JaxB RI?
Why wasn't this #XmlElementDecl elements generated during the code generation with XJC?
#Blaise: do you think it's a bug ?
property "itemsAndTuplesAndContexts" declaration:
#XmlElementRefs({ #XmlElementRef(name = "unit", namespace = "http://www.xbrl.org/2003/instance", type = Unit.class),
#XmlElementRef(name = "context", namespace = "http://www.xbrl.org/2003/instance", type = Context.class),
#XmlElementRef(name = "item", namespace = "http://www.xbrl.org/2003/instance", type = JAXBElement.class),
#XmlElementRef(name = "tuple", namespace = "http://www.xbrl.org/2003/instance", type = JAXBElement.class),
#XmlElementRef(name = "footnoteLink", namespace = "http://www.xbrl.org/2003/linkbase", type = JAXBElement.class) })
protected List<Object> itemsAndTuplesAndContexts;
I can't make this query work:
Query query = eManager.createQuery("select c FROM News c WHERE c.NEWSID = :id",News.class);
return (News)query.setParameter("id", newsId).getSingleResult();
and I got this exception:
Exception Description: Problem compiling [select c FROM News c WHERE c.NEWSID = :id].
[27, 35] The state field path 'c.NEWSID' cannot be resolved to a valid type.] with root cause
Local Exception Stack:
Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Problem compiling [select c FROM News c WHERE c.NEWSID = :id].
Why does it happen?
:id and named parameter are identical
EDIT:
my entity class
#Entity
#Table(name="NEWS")
public class News implements Serializable{
#Id
#SequenceGenerator(name = "news_seq_gen", sequenceName = "news_seq")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "news_seq_gen")
private int newsId;
private String newsTitle;
private String newsBrief;
private String newsContent;
private Date newsDate;
#Transient
private boolean selected=false;
//constructor and getters and setters
That happens because News entity does not have persistent attribute named NEWSID. Names of the persistent attributes are case sensitive in JPQL queries and those should be written with exactly same case as they appear in entity.
Because entity have persistent attribute named newsId, that should also be used in query instead of NEWSID:
select c FROM News c WHERE c.newsId = :id
entity have persistent attribute named newsId.but in query you have used NEWSID . try with this
select c FROM News c WHERE c.newsId = :id
My entity is:
#Entity
#Table(name = "TBL_PERSON_INFO")
public class Person implements Serializable {
#Id
#Column(name = "ID", nullable = false)
private Integer id;
#Column(name = "USER_ID", nullable = false)
private Integer user_id;
.
.
.
}
my query is (JPQL):
String queryName = "from Person p where p.user_id = :user_id";
so I use it like this:
javax.persistence.Query query = em.createQuery(queryName);
query.setParameter("user_id", userId);
try {
obj = query.getSingleResult();
}
catch (javax.persistence.NoResultException nre) {
logger.error("javax.persistence.NoResultException: " + nre.getMessage());
}
catch (javax.persistence.NonUniqueResultException nure) {
logger.error("javax.persistence.NonUniqueResultException: " + nure.getMessage());
}
catch (Exception e) {
e.printStackTrace();
}
if (obj == null) {
System.out.println("obj is null!");
return null;
}
Person person = (Person) obj;
It's work ;-)
I have an Jersey API that returns Odata standard responses and consumes the same. There are specific name spaces necessary for these responses. I have a package-info.java class:
#XmlSchema(
xmlns = {
#XmlNs(namespaceURI = "http://www.w3.org/2005/Atom", prefix = ""),
#XmlNs(namespaceURI = "http://schemas.microsoft.com/ado/2007/08/dataservices", prefix = "d"),
#XmlNs(namespaceURI = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata", prefix = "m")
},
namespace = "http://www.w3.org/2005/Atom",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
attributeFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED)
package my.package;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;
I use JAXB to automatically marshal and unmarshal the incoming request body and outgoing response for me. I have beans annotated for these purposes. Here is an example of one:
#XmlRootElement(name = "entry")
public class Entry
{
private String id;
private String title;
private Date updated;
private AtomLink link;
private Content content;
public Entry()
{
}
public Entry(final Content content)
{
this.content = content;
}
public Entry(final String id, final String title, final Date updated, final AtomLink link, final Content content)
{
this.id = id;
this.title = title;
this.updated = updated;
this.link = link;
this.content = content;
}
#XmlElement(name = "title")
public String getTitle()
{
return title;
}
public void setTitle(final String title)
{
this.title = title;
}
#XmlElement(name = "link")
public AtomLink getLink()
{
return link;
}
public void setLink(final AtomLink link)
{
this.link = link;
}
#XmlElement(name = "id")
public String getId()
{
return id;
}
public void setId(final String id)
{
this.id = id;
}
#XmlElement(name = "updated")
public Date getUpdated()
{
return updated;
}
public void setUpdated(final Date updated)
{
this.updated = updated;
}
#XmlElement(name = "content")
public Content getContent()
{
return content;
}
public void setContent(final Content content)
{
this.content = content;
}
}
The response comes across like this.
<ns4:entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns:ns4="http://www.w3.org/2005/Atom">
<ns4:id>TEwxaTFL</ns4:id>
<ns4:title>my resource</ns4:title>
<ns4:link href="http://127.0.0.1:8080/API/resource(TEwxaTFL)" rel="self"/>
<ns4:content type="application/xml">
<m:properties>
<d:name>temp_170_ruleset</d:name>
<d:shared>false</d:shared>
<d:autorun>false</d:autorun>
</m:properties>
</ns4:content>
</ns4:entry>
As you can see the other namespaces come across just fine. The default name space is coming back with a ns4 prefix rather than no prefix. I need it to be like this:
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns="http://www.w3.org/2005/Atom">
<id>TEwxaTFL</id>
<title>my resource</title>
<link href="http://127.0.0.1:8080/API/resource(TEwxaTFL)" rel="self"/>
<content type="application/xml">
<m:properties>
<d:name>temp_170_ruleset</d:name>
<d:shared>false</d:shared>
<d:autorun>false</d:autorun>
</m:properties>
</content>
</entry>
I've tried altering the package-info.java class to remove the name spaces:
removing
#XmlNs(namespaceURI = "http://www.w3.org/2005/Atom", prefix = ""),
and
namespace = "http://www.w3.org/2005/Atom",
and removing one at a time. Doing these things never fix the namespace prefix but affected how posts happened - mapping was not possible.
Can anyone see what I'm missing here? I really don't want to "manually" marshal every response. So I want to avoid a NamespacePrefixMapper solution, unless I can define that without manually marshaling the response. I've read where this is suppose to work.
I use Jersey 1.12, JAXB 2.2
--Outcome--
Using Moxy works. I was struggling with getting it to work because the imports used were still the JaxB that was not working for me. Syntactically using Moxy is the same so there was no overhead of updating code for us. We simply needed to add the jaxb.properties file and update our imports. The only other way we got rid of the default namespaces being like this (ns1, ns4, etc.) was to use XSL on the way out - and that sucks.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
package-info
Using the following package-info with MOXy as the JAXB provider I was able to produce the XML that you are looking for. The line that is commented out is necessary until we finish the fix for the following bug: http://bugs.eclipse.org/365457
#XmlSchema(
xmlns = {
//#XmlNs(namespaceURI = "http://www.w3.org/2005/Atom", prefix = ""),
#XmlNs(namespaceURI = "http://schemas.microsoft.com/ado/2007/08/dataservices", prefix = "d"),
#XmlNs(namespaceURI = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata", prefix = "m")
},
namespace = "http://www.w3.org/2005/Atom",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
attributeFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED)
package forum9795350;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;
For More Information
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html