convert String to Clob and vice versa in Hibernate - string

Suppose that I have a Class:
class EventTransaction {
.....
private Clob dataXML;
public Clob getDataXML() {
return dataXML;
}
public void setDataXML(Clob dataXML) {
this.dataXML = dataXML;
}
}
And Hibernate mapping xml:
<property name="dataXML" type="java.sql.Clob">
<column name="XML" sql-type="CLOB"/>
</property>
In java code, how to I convert a String to Clob and vice versa to save into to the database:
Ex: EventTransaction et = new EventTransaction();
String xml = "fdfsafafafa";
et.setDataXML(convertStringToClob(xml));
HibernateTemplate.saveOrUpdate(et);
Could you please help how to implement function convertStringToClob(String data);
Thanks,

Do this
#Column(name="XML")
#Lob
private String dataXML;
public String getDataXML() {
return dataXML;
}
public void setDataXML(String dataXML) {
this.dataXML = dataXML;
}
So there is no need to convert, and everything is done by Hibernate.
I showed it using annotations, the same thing can be done using .hbm.xml files.

Here is code I made a long time ago to convert a Clob to a String. It's meant to be used in a utility class.
public static String convertClobToString(Clob clob) throws IOException, SQLException {
Reader reader = clob.getCharacterStream();
int c = -1;
StringBuilder sb = new StringBuilder();
while((c = reader.read()) != -1) {
sb.append(((char)c));
}
return sb.toString();
}
And if I am not mistaken, to create a Clob you would do something like this
Clob myClobFile = new SerialClob("my string".toCharArray());

The limitation of 64000 characters is on the database side when you declare the XML column as VARCHAR (and not on Java String), so as long as your column XML is a CLOB, it should work.
Excerpt from working code:
Entity:
private String xml;
SQL (ORACLE):
XML CLOB,
Hibernate mapping:
<property name="xml" type="java.lang.String">
<column name="XML" length="999999" />
</property>
If you want to store the XML as a file, then you should rather use BLOBs as shown below :
Entity:
private byte[] xmlFile;
SQL (ORACLE):
XML BLOB,
Hibernate mapping:
<property name="xmlFile" type="java.io.File">
<column name="XML" />
</property>

Related

How to have Spring ContextConfiguration load both from XML and from JavaConfig

From what I've read of the Spring #ContextConfiguration annotation, it's possible to load multiple XML context files, or multiple JavaConfig classes. What I need is to load from one XML context file and one class. All the examples I've seen either load all XML, or all classes, but not both.
I'm trying to do this because I want my test class, which is just there to verify expected Spring wiring, to load my default applicationContext.xml file (presently just a copy stored in "src/test/resources, and trying to figure out how to directly specify the default one) along with a JavaConfig class that specifies some JNDI resources that need to be available. For the purposes of my test, I only need to set those JNDI resources to dummy strings, but I'd really like to specify them in an inline static class instead of an external XML file, because my tests are going to have to verify that some settings are equal to those dummy strings, and it's more maintainable if both the values and the checks are in the same file.
What I have so far, and what I've tried, can be illustrated with this:
#RunWith(SpringRunner.class)
#ContextConfiguration(value = {"/testApplicationContext.xml", "/testResources.xml"})
//#ContextHierarchy({
// #ContextConfiguration("/testApplicationContext.xml"),
// #ContextConfiguration(classes = SpringWiringTest.Config.class)
//})
#TestPropertySource(properties = { "env = tomcat", "doNotifications = false" })
public class SpringWiringTest {
And this at the end of the class:
#Configuration
public static class Config {
#Bean public String uslDatasourcesList() { return "abc"; }
#Bean public String atgDatasourcesList() { return "abc"; }
#Bean public String uslTableNamePrefixsList() { return "abc"; }
#Bean public String atgTableNamePrefixsList() { return "abc"; }
#Bean public String doNotifications() { return "false"; }
#Bean public DataSource abc() { return new DriverManagerDataSource(); }
}
If I comment out the first #ContextConfiguration and comment back in the #ContextHierarchy block, I get an error like this:
Error creating bean with name 'uslDatasourcesList': Invocation of init
method failed; nested exception is
javax.naming.NoInitialContextException: Need to specify class name in
environment or system property, or as an applet parameter, or in an
application resource file: java.naming.factory.initial
Update:
Using the guideline of picking either JavaConfig or XML as the "entry point" to configuration, here are some modified excerpts that show what I'm trying:
#RunWith(SpringRunner.class)
#ContextConfiguration
//#ContextConfiguration(value = {"file:src/main/webapp/WEB-INF/applicationContext.xml", "/testResources.xml"})
#TestPropertySource(properties = { "env = tomcat", "doNotifications = false" })
public class SpringWiringTest {
...
#BeforeClass
public static void setup() throws Exception {
SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
DataSource ds = new DriverManagerDataSource();
builder.bind("java:comp/env/abc", ds);
}
...
#Configuration
#ImportResource("file:src/main/webapp/WEB-INF/applicationContext.xml")
public static class Config {
#Bean public String uslDatasourcesList() { return "abc"; }
#Bean public String atgDatasourcesList() { return "abc"; }
#Bean public String uslTableNamePrefixsList() { return "abc"; }
#Bean public String atgTableNamePrefixsList() { return "abc"; }
#Bean public String doNotifications() { return "false"; }
#Bean public DataSource abc() { return new DriverManagerDataSource(); }
}
}
When I run my test, the bottom "Caused by" in the exception says this:
Caused by: javax.naming.NameNotFoundException: Name
[uslDatasourcesList] not bound; 1 bindings: [java:comp/env/abc]
In the alternate version, using the commented-out "#ContextConfiguration" (and commenting out the Config class and its annotations), this error does not occur.
Note that this the meat of my "testResources.xml" file:
<bean id="uslDatasourcesList" class="java.lang.String"> <constructor-arg value="abc"/> </bean>
<bean id="atgDatasourcesList" class="java.lang.String"> <constructor-arg value="abc"/> </bean>
<bean id="uslTableNamePrefixList" class="java.lang.String"> <constructor-arg value="abc"/> </bean>
<bean id="atgTableNamePrefixList" class="java.lang.String"> <constructor-arg value="abc"/> </bean>
<bean id="doNotifications" class="java.lang.String"> <constructor-arg value="false"/> </bean>
<bean id="abc" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
</bean>
Note that the bean mentioned in the error message, "uslDatasourcesList" is defined in both versions, but it's not working in the version with JavaConfig and XML mixed.
It almost appears that the beans in the "#ImportResource" annotation are evaluated on their own, before the beans declared in the JavaConfig class are merged into it.
This is clearly documented in the Spring Reference Manual in the section named Mixing XML, Groovy scripts, and annotated classes.
In summary, ...
... you will have to pick one as the entry point, and that one will have to include or import the other.
Thus, the following should hopefully solve your problem.
#RunWith(SpringRunner.class)
#ContextConfiguration
#TestPropertySource(properties = { "env = tomcat", "doNotifications = false" })
public class SpringWiringTest {
// ...
#Configuration
#ImportResource({"/testApplicationContext.xml", "/testResources.xml"})
static class Config {
// ...
}
}

JAXB and MOXy xml and json marshalling of generic list in jersey

I'm making a little restful client in Jersey, and i have come into a little trouble with supporting both XML and JSON marshaling.
The specific problem is about marshaling an object that holds a few properties, with a generic list included.
I have the following class annotated as followed:
#XmlRootElement
public class Block<E> {
private String headerText;
private List<E> elements;
public Block() {
}
#XmlElement
public String getHeaderText() {
return headerText;
}
#XmlElementWrapper(name = "elements")
#XmlElements({
#XmlElement(name = "element", type=Foo.class),
#XmlElement(name = "element", type=Bar.class)
})
public List<E> getElements() {
return elements;
}
}
The XML comes out fine:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<block>
<elements>
<element>
<id>1</id>
<title>Title01</title>
</element>
<element>
<id>2</id>>
<title>Title02</title>
</element>
</elements>
<headerText>FooBarHeader</headerText>
</block>
but the JSON is formatted like this
{
-elements : {
-element: [
- {
id : 1
title : "Title01"
}
- {
id : 2
title : "Title02"
}
]
}
headerText : "HeaderText"
}
I would of course be interested in not having the "element" property in my JSON output, and only have elements: [{}...{}]
I have already setup a ContextResolver that creates a MOXyConfig with properties for JSON_WRAPPER_AS_ARRAY_NAME - and this works fine for fx. A List<String> where I only have to declare the property with #XmlElement instead of #XmlElements.
Anyone who know of a solution of this problem?
JSON_WRAPPER_AS_ARRAY_NAME Property
The effect of the JSON_WRAPPER_AS_ARRAY_NAME property (see: http://blog.bdoughan.com/2013/03/binding-to-json-xml-handling-collections.html) depends on whether the item names are significant or not,
Insignificant Item Names
Below we know that each item in the collection is an instance of Foo or an instance of a subclass of Foo.
#XmlElementWrapper(name = "elements")
#XmlElement(name = "element")
public List<E> getElements() {
return elements;
}
Significant Item Names
In the case of #XmlElements the item name is significant since it tells us which class we need to instantiate on the unmarshal and can not be excluded.
#XmlElementWrapper(name = "elements")
#XmlElements({
#XmlElement(name = "foo", type=Foo.class),
#XmlElement(name = "bar", type=Bar.class)
})
public List<E> getElements() {
return elements;
}
What You Can Do
You can use MOXy's externmal mapping document to override the mapping for the elements property to the following:
#XmlElementWrapper(name = "elements")
#XmlElement(name = "foo")
public List<E> getElements() {
return elements;
}
Then the JAXBContext for XML will be based on the annotations, and the JAXBContext for JSON will be based on the annotatons and external mapping document.
For More Information
http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
http://blog.bdoughan.com/2011/09/mapping-objects-to-multiple-xml-schemas.html
Try registering another JSON Entity Provider, which will disable automatically Moxy for JSON marshalling (see the ref). If you enable e.g Jackson, you will have its own annotations to control how everything is marshalled.

Dozer, how to map from java.util.Map to complex type?

I'd like to map from a java.util.Map to a complex type, let's call it Abc.
<mapping>
<class-a>java.util.Map</class-a>
<class-b bean-factory="xyz.AbcBeanFactory" factory-bean-id="AbcBeanFactory">
xyz.Abc
</class-b>
<field>
<a>Name</a>
<b>companyName</b>
</field>
</mapping>
With that I get this error (which is comprehensible):
org.dozer.MappingException: No read or write method found for field (Name) in class (interface java.util.Map)
Ok, how do I map from a java.util.Map that has an entry with the key 'Name'? Do I have to create a wrapper object that holds that java.util.Map and provide getters/setters for each entry in that map that I want to map?
You can find details for mapping a Map in the Dozer documentation. You need to provide a key not a plain field. Here is an example:
Class Abc:
package com.test;
public class Abc {
private String companyName;
private String companyAddress;
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getCompanyAddress() {
return companyAddress;
}
public void setCompanyAddress(String companyAddress) {
this.companyAddress = companyAddress;
}
}
Mapping file:
<mapping>
<class-a>java.util.Map</class-a>
<class-b>com.test.Abc</class-b>
<field>
<a key="name">this</a>
<b>companyName</b>
</field>
<field>
<a key="address">this</a>
<b>companyAddress</b>
</field>
</mapping>
Test code:
Map<String, String> map = new HashMap<String, String>();
map.put("name", "Company Inc.");
map.put("address", "XYZ Commercial Street");
Abc destObject = dozerMapper.map(map, Abc.class);

Jaxb EclipseLink/MOXy : Is it possible to specify the names of get/set methods

I have a quite simple question :
Say I have a model class defined like this :
public class Test{
private String testAttribute;
public Test(){
}
public String getFormattedTestAttribute(){
return testAttribute + "A nice formatted thingy"; //right, this is just an example
}
public void setTestAttribute(String value){
testAttribute = value;
}
}
You can see that I have a standard setter for testProperty but the getter has a different name : getFormattedTestProperty().
Is it possible into Jaxb/Moxy to specify which getter to use for a specific property ?
I'm using MOXy implementation with external metadata bindings file. The project which I'm working on used tu use Castor. Into Castor's mapping files, you could specify which getter/setter to use like that :
<field name="testAttribute"
get-method="getFormattedTestAttribute">
<bind-xml name="test-attribute" node="attribute"/>
</field>
Is the same kind of thing possible with moxy's external metadata ?
If that kind of customization isn't supported, is it possible to mark a field as read-only and another as write-only ? so I could declare a read-only property named "formattedTestAttribute" and a write-only property named "testAttribute" into the metadata bindings file ?
<!-- read only property -->
<xml-element java-attribute="formattedTestAttribute" xml-path="#test-attribute" />
<!-- write only property -->
<xml-element java-attribute="testAttribute" xml-path="#test-attribute" />
Please note that I have very limited control over the model classes.
Thanks in advance for your answers.
You could represent this in EclipseLink JAXB (MOXy)'s external mapping document as follows:
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum8834871">
<java-types>
<java-type name="Test" xml-accessor-type="PUBLIC_MEMBER">
<xml-root-element/>
<java-attributes>
<xml-element
java-attribute="testAttribute"
name="test-attribute">
<xml-access-methods
get-method="getFormattedTestAttribute"
set-method="setTestAttribute"/>
</xml-element>
<xml-transient java-attribute="formattedTestAttribute"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
Test
I have modified your Test class, to put some logic in the get/set methods.
package forum8834871;
public class Test{
private String testAttribute;
public Test(){
}
public String getFormattedTestAttribute(){
return "APPENDED_ON_GET " + testAttribute;
}
public void setTestAttribute(String value){
testAttribute = "APPENDED_ON_SET " + value;
}
}
Demo
package forum8834871;
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum8834871/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Test.class}, properties);
File xml = new File("src/forum8834871/input.xml");
Unmarshaller unmarshaller = jc.createUnmarshaller();
Test test = (Test) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(test, System.out);
}
}
input.xml
<?xml version="1.0" encoding="UTF-8"?>
<test>
<test-attribute>ORIGINAL</test-attribute>
</test>
Output
<?xml version="1.0" encoding="UTF-8"?>
<test>
<test-attribute>APPENDED_ON_GET APPENDED_ON_SET ORIGINAL</test-attribute>
</test>

JaxB EclipseLink/MOXy : Supposedly empty date marshalled as today's date instead of no writing a node for it

Once again I have a question about Eclipselink/MOXy with external metadata mapping file.
I have a reference xml which applies to a class. This xml contains data that applies to some but not always all the properties that the class can contain.
I also have a custom datetime adapter set for the date fields.
My problem is that the xml I'm unmarshalling does not contain any data for the endDate property, yet when I do this simple test :
Unmarshall reference xml to the class
Marshall that class to a new xml file
Compare the two xml files
That property endDate (which should not be marshalled since it has not been set) is marshalled as 09/01/2012 17:05:28 (it's always marshalled as a new Date() set to the current time).
Here is a sample XML Metadata file :
<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
version="2.1">
<java-types>
<java-type name="sample.clazz.Task" xml-accessor-type="NONE">
<xml-root-element name="Task" />
<xml-type prop-order="startDate endDate id ci ch cr" />
<java-attributes>
<xml-element java-attribute="startDate" xml-path="StartDate/text()">
<xml-java-type-adapter value="utils.JaxBDateTimeAdapter" type="java.util.Date"/>
</xml-element>
<xml-element java-attribute="endDate" required="false" xml-path="EndDate/text()">
<xml-java-type-adapter value="utils.JaxBDateTimeAdapter" type="java.util.Date"/>
</xml-element>
<xml-element java-attribute="id" xml-path="TaskId/text()" />
<xml-element java-attribute="ci" xml-path="CIPR/text()" />
<xml-element java-attribute="ch" xml-path="CHPR/text()" />
<xml-element java-attribute="cr" xml-path="CRPR/text()" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
Here is the class :
package sample.clazz;
public class Task{
private int id;
private Date startDate;
private Date endDate;
private String ci;
private String ch;
private String cr;
public Task(){
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getCi() {
return ci;
}
public void setCi(String ci) {
this.ci = ci;
}
public String getCh() {
return ch;
}
public void setCh(String ch) {
this.ch = ch;
}
public String getCr() {
return cr;
}
public void setCr(String cr) {
this.cr = cr;
}
}
Here is my custom DateTimeAdapter :
package utils;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class JaxBDateTimeAdapter extends XmlAdapter<String, Date> {
#Override
public String marshal(Date d) throws Exception {
if(d != null){
return DateUtil.getFormatedDateTimeString(d);
}
else{
return null;
}
}
#Override
public Date unmarshal(String d) throws Exception {
if(d != null && !"".equals(d)){
return DateUtil.getDateFromString(d);
}
else{
return null;
}
}
}
Here is my reference XML
<?xml version="1.0" encoding="UTF-8"?>
<Task>
<TaskId>147</TaskId>
<CRPR>0087</CRPR>
<CIPR>A683557</CIPR>
<CHPR>BV</CHPR>
<StartDate>22/01/2009 20:56:29</StartDate>
</Task>
and Here is the XML I'm getting when re-marshalling the object :
<?xml version="1.0" encoding="UTF-8"?>
<Task>
<TaskId>147</TaskId>
<CRPR>0087</CRPR>
<CIPR>A683557</CIPR>
<CHPR>BV</CHPR>
<StartDate>01/01/2012 20:56:29</StartDate>
<EndDate>09/01/2012 17:05:28</EndDate> <!-- That element should not exist ! -->
</Task>
It seems like Jaxb generates a new date for the empty field, how can I tell him via the external metadata mapping file not to generate nodes for empty or null values ? I tried to set required=false on the metadata file, and I tried testing with my custom DateTimeAdapter if the values were null, but it seems Jaxb creates a new Date object and passes it to the marshal method of the Adapter. I cant think of any way of preventing him to do this.
As for my previous questions, I have no control over the incoming XML's or the model classes.
Please note : this data is a sample I wrote, it may not be accurate since I cannot expose real data or names, there might be some typing errors.
Thanks for your help.
I'm the EclipseLink JAXB (MOXy) lead and I have not been able to reproduce your issue. It may be possible that there is a problem in your DateUtil class. The following is what I have tried:
oxm.xml
I made a small change to your metadatafile. Basically I changed it to specify the package name on the xml-bindings element rather than the individual java-type elements:
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
version="2.3"
package-name="sample.clazz">
<java-types>
<java-type name="Task" xml-accessor-type="NONE">
<xml-root-element name="Task" />
<xml-type prop-order="startDate endDate id ci ch cr" />
<java-attributes>
<xml-element java-attribute="startDate" xml-path="StartDate/text()">
<xml-java-type-adapter value="forum8791782.JaxBDateTimeAdapter" type="java.util.Date"/>
</xml-element>
<xml-element java-attribute="endDate" required="false" xml-path="EndDate/text()">
<xml-java-type-adapter value="forum8791782.JaxBDateTimeAdapter" type="java.util.Date"/>
</xml-element>
<xml-element java-attribute="id" xml-path="TaskId/text()" />
<xml-element java-attribute="ci" xml-path="CIPR/text()" />
<xml-element java-attribute="ch" xml-path="CHPR/text()" />
<xml-element java-attribute="cr" xml-path="CRPR/text()" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
DateUtil
You did not provide an implementation of DateUtil in your question, so I used the following. My guess is there is code in your implementation of DateUtil that is causing the output that you are seeing:
package forum8791782;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
private static SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
public static String getFormatedDateTimeString(Date d) {
return formatter.format(d);
}
public static Date getDateFromString(String d) {
try {
return formatter.parse(d);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
Demo
Below is the code I used to run this example. input.xml is the reference XML you cite in your question:
package forum8791782;
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.Version;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import sample.clazz.Task;
public class Demo {
public static void main(String[] args) throws Exception {
System.out.println(Version.getVersionString());
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum8791782/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Task.class}, properties);
File xml = new File("src/forum8791782/input.xml");
Unmarshaller u = jc.createUnmarshaller();
Task task = (Task) u.unmarshal(xml);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(task, System.out);
}
}
Output
The following is the output I get from running the sample code. I do not see the EndDate element written out.
2.3.2.v20111125-r10461
<?xml version="1.0" encoding="UTF-8"?>
<Task>
<StartDate>22/01/2009 20:56:29</StartDate>
<TaskId>147</TaskId>
<CIPR>A683557</CIPR>
<CHPR>BV</CHPR>
<CRPR>0087</CRPR>
</Task>

Resources