Date conversation error during jaxb marshall on a JPA object using eclipselink - jpa

I stuck on this Date conversation error for quite some time ...
I am using eclipselinks, openJPA under TomcatEE environment, and trying to use jaxb doing marshalling. I met a problem for marshall one JPA object, which contains Date, TimeStamp elements.
The exception message is ---
javax.xml.bind.MarshalException
- with linked exception:
[Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [3/19/12 12:00 AM], of class [class org.apache.openjpa.util.java$util$Date$proxy], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[createTs-->createTs/text()]] with descriptor [XMLDescriptor(xxx.xxxx.xxx.xxxx.entities.ApplicationEntity --> [])], could not be converted to [class java.util.Date].]
The strange thing is jaxb converting works OK for some customers, but not some other customer. I tried to put #XmlElement(type=Date.class) for this field crtTs, It doesn't work.
Thanks for your help in advance.
LL

I have been able to reproduce the issue you are seeing. You can use the following bug to track our progress on this issue:
http://bugs.eclipse.org/383639
WORK AROUND
DateAdapter
You could use an XmlAdapter to convert the problematic date into a proper java.util.Date.
package forum11145711;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class DateAdapter extends XmlAdapter<Date, Date>{
#Override
public Date unmarshal(Date date) throws Exception {
return date;
}
#Override
public Date marshal(Date date) throws Exception {
if(null == date) {
return date;
}
return new Date(date.getTime());
}
}
Root
The #XmlJavaTypeAdapter annotation is used to leverage the XmlAdapter:
package forum11145711;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
public class Root {
private Date date;
#XmlJavaTypeAdapter(DateAdapter.class)
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
MyDate
Below is the subclass of java.util.Date I'm using in this example.
package forum11145711;
import java.util.Date;
public class MyDate extends Date {
}
Demo
Below is some demo code you can use to prove that everything works:
package forum11145711;
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(Root.class);
Root root = new Root();
root.setDate(new MyDate());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<date>2012-06-27T10:39:49.081</date>
</root>

Related

How to insert Date object with the latest mongojack?

so in my object, I have private Date date; when I insert I got this exception:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: JsonGenerator of type org.mongojack.internal.object.document.DocumentObjectGenerator not supported: org.mongojack.internal.DateSerializer is designed for use only with org.mongojack.internal.object.BsonObjectGenerator or org.mongojack.internal.stream.DBEncoderBsonGenerator or com.fasterxml.jackson.databind.util.TokenBuffer (through reference chain: com.test.DocumentWrapper["date"])
I am trying to set up the mongo TTL by using that date field.
I have had the same issue recently: to store date as Date object into MongoDB via MongoJack.
First of all, I used MongoJack 2.10.0 version.
And it requires to create own Serializer and Deserializer.
public class Serializer extends JsonSerializer<DateTime> {
#Override
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeObject(new Date(value.getMillis()));
}
}
public class Deserializer extends JsonDeserializer<DateTime> {
private static final DateDeserializer DATE_DESERIALIZER = new DateDeserializer();
#Override
public DateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Date date = DATE_DESERIALIZER.deserialize(p, ctxt);
return date == null ? null : new DateTime(date);
}
}
.....
#JsonSerialize(using = Serializer.class)
#JsonDeserialize(using = Deserializer.class)
private DateTime testDate;
public DateTime getTestDate() {
return testDate;
}
public void setTestDate(DateTime testDate) {
this.testDate = testDate;
}
......
In my case, I converted Date into joda DateTime to keep consistency with my code but it's possible to change to another type (LocalDateTime, OffsetDateTime, etc.)
To solve this issue, please use the 2.10.0 version which has fixed this bug.

Java Date ISO8601

I have the the following class used with JPA and JAX-RS:
import java.util.Date;
public class UserModel implements Serializable{
private Date created;
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
When I access this class via Response resource I get the "created" in ISO8601 format:
2013-08-21T22:06:36+02:00
However when I access it in Java code (System.out.println) I get it in the following format:
Wed Aug 21 22:06:36 CEST 2013
Is there any way to get it always in ISO8601 format?
Apparently for java automatically transforms Date format to the latter one.
Here is how I solved it:
I have changed the following:
public Date getCreated() {
return created;
}
to
public String getCreated() {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
return df.format(created);
}

Moxy - Creating XML element with no corresponding Java Property

I've been using Moxy to successfully marshall / unmarshall complex xml types into a more simple java Structure. In particular, I'm working with ISO Pain 20022 messages and there are a number of fields that are present in the XML that we don't care about:
<?xml version="1.0" encoding="UTF-8"?>
<iso:Document xmlns:iso="urn:iso:std:iso:20022:tech:xsd:pain.001.001.04" >
<iso:CstmrCdtTrfInitn>
<iso:GrpHdr>
<iso:MsgId>OriginalMessageID</iso:MsgId>
<iso:CreDtTm>2013-05-29T20:02:22.615</iso:CreDtTm>
<iso:NbOfTxs>1</iso:NbOfTxs>
<iso:InitgPty/>
</iso:GrpHdr>
<iso:PmtInf>
...
</iso:Document>
Here is my oxm bindings file piece:
<xml-element java-attribute="messageId" xml-path="iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:MsgId/text()"/>
<xml-element java-attribute="creationDateTime" xml-path="iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:CreDtTm/text()"/>
I need to generate the additional two xml elements iso:NbOfTxs and iso:InitgPty which will always be the same and there is no corresponding property for these on the java class that is generating the xml.
Is this possible?
Thanks.
I am still working on this use case. Below is the XML I am currently able to generate (I recognize that it's not correct).
Output
<?xml version="1.0" encoding="UTF-8"?>
<iso:Document xmlns:iso="urn:iso:std:iso:20022:tech:xsd:pain.001.001.04">
<iso:CstmrCdtTrfInitn>
<iso:GrpHdr>
<iso:MsgId>OriginalMessageID</iso:MsgId>
</iso:GrpHdr>
</iso:CstmrCdtTrfInitn>
<iso:CstmrCdtTrfInitn>
<iso:GrpHdr>
<iso:CreDtTm>2013-05-29T20:02:22.615</iso:CreDtTm>
<iso:NbOfTxs>1</iso:NbOfTxs>
<iso:InitgPty/>
</iso:GrpHdr>
</iso:CstmrCdtTrfInitn>
</iso:Document>
Document
Below is a simplified version of your domain model:
import java.util.Date;
public class Document {
private String messageId;
private Date creationDateTime;
}
oxm.xml
In the metadata below I'm trying to use an XmlAdapter to convert the Date property into a more complex object that can write out the other 2 XML elements.
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum16839007">
<xml-schema
namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.04"
element-form-default="QUALIFIED">
<xml-ns prefix="iso" namespace-uri="urn:iso:std:iso:20022:tech:xsd:pain.001.001.04"/>
</xml-schema>
<java-types>
<java-type name="Document" xml-accessor-type="FIELD">
<xml-root-element name="Document"/>
<java-attributes>
<xml-element java-attribute="messageId" xml-path="iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:MsgId/text()"/>
<xml-element java-attribute="creationDateTime" xml-path=".">
<xml-java-type-adapter value="forum16839007.ExtraAdapter"/>
</xml-element>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
ExtraAdapter
Here is the XmlAdapter that converts a Date into a more complex object.
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
public class ExtraAdapter extends XmlAdapter<ExtraAdapter.Extra, Date>{
public static class Extra {
#XmlPath("iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:CreDtTm/text()")
public Date creationDateTime;
#XmlPath("iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:NbOfTxs/text()")
public final int NbOfTxs = 1;
#XmlPath("iso:CstmrCdtTrfInitn/iso:GrpHdr/iso:InitgPty/text()")
public final Empty initgPty = new Empty();
}
public static class Empty {
}
#Override
public Date unmarshal(Extra extra) throws Exception {
return extra.creationDateTime;
}
#Override
public Extra marshal(Date date) throws Exception {
Extra extra = new Extra();
extra.creationDateTime = date;
return extra;
}
}
Demo
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum16839007/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Document.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum16839007/input.xml");
Document document = (Document) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(document, System.out);
}
}

MOXy's #XmlCDATA seems to have no affect

I would like to have the following returned to the browser (view source)
<content>
<![CDATA[Please show this inside a unescaped CDATA tag]]>
</content>
But I acutally get
<content>
Please show this inside a unescaped CDATA tag
</content>
If, I change the value of content to be
&lt ;![CDATA[Please show this inside a unescaped CDATA tag]]&gt ;
, the less than and the greater than for the tag are escaped.
Wondering how to achieve what I wanted????
Here is my code
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/myRequest")
public class MyRestClass {
#GET
#Path("{myPathNumber}")
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Object doInquiry(#PathParam("myPathNumber") String myPathNumber) {
try {
return new MyObject();
} catch (Exception e) {
return "exception " + e.getMessage();
}
}
}
package org.openengine.wink;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
#XmlRootElement
public class MyObject implements Serializable {
#XmlElement
#XmlCDATA
private String content = "Please show this inside a unescaped CDATA tag";
}
in package org.openengine.wink I have a file, jaxb.properties, with the following content
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
CLASSPATH
My best guess is that EclipseLink JAXB (MOXy) is not correctly configured on your classpath, and the JAXB RI is being used as the JAXB (JSR-222) provider in your environment.
METADATA
The EclipseLink JAXB (MOXy) metadata you have provided appears to be correct. This can be verified with the following standalone demo code.
MyObject
By default JAXB (JSR-222) implementations look for metadata on the property (getter/setter). Since you have annotated the field I would recommend using the #XmlAccessorType(XmlAccessType.FIELD annotation (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).
package org.openengine.wink;
import java.io.Serializable;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class MyObject implements Serializable {
#XmlElement
#XmlCDATA
private String content = "Please show this inside a unescaped CDATA tag";
}
jaxb.properties
To specify MOXy as your JAXB provider you need to have the EclipseLink binaries on your classpath and have a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
package org.openengine.wink;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(MyObject.class);
MyObject myObject = new MyObject();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(myObject, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<myObject>
<content><![CDATA[Please show this inside a unescaped CDATA tag]]></content>
</myObject>
For More Information
http://blog.bdoughan.com/2010/07/cdata-cdata-run-run-data-run.html

How do I request a subset of XMLElements using MOXy?

I have a RESTful service that needs to return only a few of the XmlElements if "selectors" are submitted with the request. The URL will take the form of:
/merchants/{merchantId}/profile?selectors=<field1|field2|....|fieldN>
The selectors are optional, and so far I have implemented the service for the full set of elements to be returned for {merchantId} without selectors specified. Now I'm trying to figure out how to add in this added functionality. I'm sure this is covered in documentation but I can't find where. Any RTFM pointers would be appreciated. Thanks.
EclipseLink JAXB (MOXy) does not currently offer a mechanism to selectively indicate which fields/properties are included on a per marshal operation. This sounds like an interesting use case. I would appreciate if you could enter this as an enhancement request using the following link:
https://bugs.eclipse.org/bugs/enter_bug.cgi?product=EclipseLink
Below is an example of how you could use a stateful XmlAdapter to implement this use case by exploiting the fact that a JAXB (JSR-222) will not marshal an element when the value is null (see: http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html).
FieldAdapter
Since we are going to leverage stateful XmlAdapters we're going to need one per field. Since all our XmlAdapters will perform the same logic we can create a super class that the others can extend from.
package forum13094195;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class FieldAdapter<T> extends XmlAdapter<T, T> {
private boolean include;
public FieldAdapter() {
this.include = true;
}
public FieldAdapter(boolean include) {
this.include = include;
}
#Override
public T marshal(T value) throws Exception {
if(include) {
return value;
}
return null;
}
#Override
public T unmarshal(T value) throws Exception {
return value;
}
}
Field1Adapter
package forum13094195;
public class Field1Adapter extends FieldAdapter<String> {
public Field1Adapter() {}
public Field1Adapter(boolean include) {
super(include);
}
}
Field2Adapter
package forum13094195;
public class Field2Adapter extends FieldAdapter<Integer>{
public Field2Adapter() {}
public Field2Adapter(boolean include) {
super(include);
}
}
Field3Adapter
package forum13094195;
public class Field3Adapter extends FieldAdapter<String> {
public Field3Adapter() {}
public Field3Adapter(boolean include) {
super(include);
}
}
Merchant
The #XmlJavaTypeAdapter annotation is used to specify an XmlAdapter on a field/property.
package forum13094195;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Merchant {
#XmlJavaTypeAdapter(Field1Adapter.class)
String field1;
#XmlJavaTypeAdapter(Field2Adapter.class)
int field2;
#XmlJavaTypeAdapter(Field3Adapter.class)
String field3;
}
Demo
The demo code below demonstrates how to set a stateful XmlAdapter on the Marshaller.
package forum13094195;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Merchant.class);
Merchant merchant = new Merchant();
merchant.field1 = "A";
merchant.field2 = 2;
merchant.field3 = "C";
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(merchant, System.out);
marshaller.setAdapter(new Field1Adapter(false));
marshaller.setAdapter(new Field2Adapter(false));
marshaller.setAdapter(new Field3Adapter(true));
marshaller.marshal(merchant, System.out);
}
}
Output
Below is the output from running the demo code. By default the entire object is marshalled out. The second document marshalled does not contain the fields we excluded.
<?xml version="1.0" encoding="UTF-8"?>
<merchant>
<field1>A</field1>
<field2>2</field2>
<field3>C</field3>
</merchant>
<?xml version="1.0" encoding="UTF-8"?>
<merchant>
<field3>C</field3>
</merchant>
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
In EclipseLink 2.5.0 we released a new feature called Object Graphs that enables you to marshal/unmarshal a subset of mapped fields/properties.
// Create the Object Graph
ObjectGraph subset = JAXBHelper.getJAXBContext(jc).createObjectGraph(Merchant.class);
subset.addAttributeNodes("field1", "field1", "fieldN");
// Output XML - Based on Object Graph
marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, subset);
marshaller.marshal(customer, System.out);
For More Information
http://blog.bdoughan.com/2013/03/moxys-object-graphs-partial-models-on.html