Serializing An Object Into XML Java - xml-serialization

In C# we use serializer.ToXmlString/FromXmlString.
Is there any Java equivalent for this?

In java you use a javax.xml.transform.Transformer for DOM objects.
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(myDocument), new StreamResult(targetFile));
For regular java objects you might want to try XStream.

Related

MappingJackson2HttpMessageConverter & Serialization

Based on the below guide
https://spring.io/guides/gs/rest-service/
MappingJackson2HttpMessageConverter converts the Greeting Object to JSON. Question is, why isn't Greeting Object implementing Serializable? Is it a miss in the guide or not required?
Implementing Serializable is necessary for native Java serialization.
JSON marshalling with Jackson doesn't need it.

Implementing Hypermedia in RESTful JAX-RS Apache CXF

I am working in a RESTful application developed in Apache CXF and I would like to introduce hypermedia functionality to it.
Most of our jaxrs:serviceBeans follow this template:
#GET
#Path("/{exampleId}")
public ExampleJSON get(#PathParam("exampleId") Integer exampleId) {
ExampleJSON example;
// Load data from repository here...
// Add link to self.
String href = javax.ws.rs.core.Link.fromResource(ExampleService.class).build().getUri().toString();
// HypermediaLink is a custom object to hold a "href" and "rel" strings
HypermediaLink linkToSelf = new HypermediaLink();
linkToSelf.setHref(href + example.getId());
linkToSelf.setRel("self");
// Inherited method, just adds a HypermediaLink to a collection in the parent class
example.addHypermediaLink(linkToSelf);
// Return JSON compatible object, JACKSON will serialize it nicely.
return example;
}
This is the basic concept. Keep in mind that I simplified this code for explanation purposes; so, it can be easily understood.
This code works fine; but I am wondering if there is a better way to do this with Apache CXF. I have some ideas for how to enhancing it; however, it will require some custom annotations.
I see some examples using Jersey, but I would like to stick with Apache CXF.
Any help would be appreciated.
Thanks
I would leverage some features of JAX-RS and / or Jackson to implement the link adding under the hood at the serialization level. So you wouldn't need to have a specific field for the link within the bean itself.
You could implement a custom MessageBodyWriter to generate a different JSON payload (for example) for your POJOs than the default. So you could dynamically add the link.
See this answer for more details: How to write an XML MessageBodyWriter provider with jersey.
If you use Jackson for the serialization, you could implement a custom serializer. Note that this is generic and will work for all supported format of Jackson.
Below is a sample code:
public class LinkBeanSerializer extends JsonSerializer<SomeBean> {
#Override
public void serialize(SomeBean bean, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeStartObject();
// Fields
jgen.writeNumberField("id", bean.getId());
// Things could be generic using reflection
// Link
String href = javax.ws.rs.core.Link.fromResource(SomeBean.class).build().getUri().toString();
HypermediaLink linkToSelf = new HypermediaLink();
linkToSelf.setHref(href + bean.getId());
linkToSelf.setRel("self");
jgen.writeObjectField("hypermediaLink", linkToSelf);
jgen.writeEndObject();
}
}
Note that we could make this serializer more generic I think (something like extends JsonSerializer<Object>)
See this answer for more details: Processing JSON response using JAX-RS (how to register the custom serializer within JAX-RS, ...).
Perhaps implementing a WriterInterceptor could solve your problem but there is impact on the beans since you need to have field hypermediaLink. The interceptor could be responsible of filling the field.
See this answer for more details: Jersey Update Entity Property MessageBodyWriter.
IMO the more convenient solution is the second one. It's transparent and support all the formats supported by Jackson.
Hope it helps you,
Thierry

Custom field serializer / deserializer

I am able to load some entities into ElasticSearch with out-of-the box Spring Data ElasticSearch. The thing is my model classes contemplate many properties and for some of those I don't want my representation (typing) be reflected into ES.
#Field(serializer = MyCustomSerializer, deserializer = MyCustomDeserializer)
private SomeClass someObject;
I'd like, for example, for SomeClass to be serialized as a String, so I can query it as such. Also, when reading data from ES, I want to be able to write a custom deserializer (MyCustomDeserializer) to convert this String into my own model.
Is there any way I can accomplish that??
Thanks
Spring Data ElasticSearch uses jackson to serialize the fields, so you could achieve custom serialization logic by defining:
#JsonSerialize(using = MyCustomSerializer.class)
#JsonDeserialize(using = MyCustomDeserializer.class)
private SomeClass someObject;
Or configure your mapping globally in a jackson ObjectMapper, replacing the default EntityMapper from spring-data-elasticsearch. More on that here.

Meshing Acceleo with Xtext

I am in the middle of an Acceleo Transformation aimed at producing code (i.e. Java) from an input UML model.
Some elements of this UML model (i.e. Activities Opaque actions) contain some text which is conform to an Xtext grammar and I'd like to get the equivalent AST Ecore representation in the Acceleo transformation.
To this end I have developed a Java class with a method which takes as input a string, containing the DSL excerpt, and produces an Ecore model conform to it (see http://www.eclipse.org/forums/index.php/m/901947/#msg_901947 for further details). I have tested it in a separate Java application and it seems it works properly.
I have therefore written a simple Acceleo module (i.e. getDSLModel) wrapping that java class and enabling me to get the Ecore model from the DSL textual representation.
Suppose my DSL (and the equivalent Ecore) consist of a root element named DSLModel containing a (0..*) number of DSLStatements (this is a simplification).
When in Acceleo I invoke the wrapper from a string, containing a correct DSL script, I have noticed it correctly returns a ModelImpl.
['statement1;statement2'.getDSLModel()/]
so the Java service and the Xtext parse is working.
However if I try to get the model statements, i.e.:
['statement1;statement2'.getDSLModel().statements/]
it returns an "invalid" string. So I can't use it in a for loop
I have therefore tried to call the eAllContents() OCL service from the model instance i.e.:
['statement1;statement2'.getDSLModel().eAllContents()/]
and it actually returns the list of statements. I do not understand why the features of the Ecore entities returned from the Xtext parser are not working properly.
Here is the Java service which turns a string into a instance of my DSL model (Ecore AST). I have tested it with an independent Java application and it works fine!
public class GetDSLModel {
public DSLModel getDSLModel(String expression){
DSLStandaloneSetupGenerated dslsas = new DSLStandaloneSetupGenerated();
Injector injector = dslsas.createInjectorAndDoEMFRegistration();
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
Resource resource = resourceSet.createResource(URI.createURI("dummy:/example.dsl"));
InputStream in = new ByteArrayInputStream(expression.getBytes());
try {
resource.load(in, resourceSet.getLoadOptions());
DSLModel model = (DSLModel) resource.getContents().get(0);
return model;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
Now I need the AST in the main Acceleo (UML2Text) transformation thus here is the Acceleo wrapper
[query public getDSLModel(str:String): DSLModel = (invoke('sfg.baleno.src.mloaders.GetDSLModel','getDSLModel(java.lang.String)',Sequence{str})).oclAsType(DSLModel)/]
here is what I get if run it
input: ['statement1;statement2'.getDSLModel()/]
output: mypackage.dsl.impl.DSLModelImpl#a1c7a
input: ['statement1;statement2'.getDSLModel().statements/] (Syntactically VALID)
output: invalid
input: ['statement1;statement2'.getDSLModel().eAllContents()/]
output: mypackage.dsl.impl.DSLStatement#e53202 (......
UPDATE
To the Java Class of the main Acceleo module I have added the following lines
#Override
public void initialize(EObject element, File folder, java.util.List<? extends Object> arguments) throws IOException { preInitialize();
super.initialize(element, folder, arguments);
}
#Override
public void initialize(URI modelURI, File folder, java.util.List<?> arguments) throws IOException {
preInitialize();
super.initialize(modelURI, folder, arguments);
}
protected void preInitialize() {
DSLStandaloneSetup.doSetup();
}
and
#Override
public void registerPackages(ResourceSet resourceSet) {
super.registerPackages(resourceSet);
if (!isInWorkspace(org.eclipse.uml2.uml.UMLPackage.class)) {
resourceSet.getPackageRegistry().put(org.eclipse.uml2.uml.UMLPackage.eINSTANCE.getNsURI(), org.eclipse.uml2.uml.UMLPackage.eINSTANCE);
}
if (!isInWorkspace(mypackages.DSLPackage.class)) {
resourceSet.getPackageRegistry().put(mypackages.DSLPackage.eINSTANCE.getNsURI(), mypackages.DSLPackage.eINSTANCE);
}
EcoreUtil.resolveAll(resourceSet);
}
but it still behaves the same.
UPDATE
At this link you temporary find a zipped file of an example EMF workspace containing an Acceleo and a XText project reproducing the issue. The weird thing is that if you run it as a Java application it works but if you run it as an Acceleo application it does not...
https://docs.google.com/open?id=0B2_ovo8IiZaZaXdNdFdPMTI4Yjg
In the top left corner you should find a File menu from which you can download the zip file.
I am unfortunately not that familiar with Xtext ... but I believe your problem lies in the way you load your dsl from within the java service : you are generating in the context of a running Eclipse ("acceleo application"), yet you load your model as if you were in standalone : new DSLStandaloneSetup, createInjector...
I believe that this way of loading your model gives you two instances of the Xtext metamodels and factories, making OCL fails to retrieve the feature "statements" when you try to obtain its values.
One possible way I can think of to bypass this would be to change your service to take an EObject of any sort as parameter and use its resource set to load your dsl (thus using the resource set you've initialized in the launcher, the one Acceleo uses, instead of your own) :
public DSLModel getDSLModel(String expression, EObject eObj){
ResourceSet rSet = eObj.eResource().getResourceSet();
[...]
}
With that, you should not need the second Xtext initialization you do from the service ... If it does not work tough, I don't really have a solution to propose other than to go to the Xtext forums and ask there how to make an application that can load a DSL and work both in standalone and in a pluginized environment.

How to use GWT SerializationStreamFactory

I am trying to serialize a object in GWT using SerializationFactory, but I am not able to get it working. Here is the sample code of my POC:
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamFactory;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
...........
Some code here....
.........
......
SerializationStreamFactory factory = (SerializationStreamFactory) GWT.create(MyClass.class);
SerializationStreamWriter writer = factory.createStreamWriter();
try {
writer.writeObject(new MyClass("anirudh"));
String value = writer.toString();
SerializationStreamReader reader = factory.createStreamReader(value);
MyClass myObj = (MyClass) reader.readObject();
System.out.println(myObj.getName());
} catch (SerializationException e) {
e.printStackTrace();
}
It gave me the following exception
Caused by: java.lang.RuntimeException: Deferred binding failed for 'com.anirudh..client.MyClass' (did you forget to inherit a required module?)
also in my code the class whose object I am trying to serialize implements IsSerializable
MyClass implements IsSerializable
I don't want to use GWT Auto-Bean framework because it does not fit my use case. Also I am not using GWT-RPC framework and right now I am quite adamant about using SerializationStreamFactory :D because I seriously want to know how this thing works.
Can anyone share a working example of SerializationStreamFactory or help me out pointing any mistake(s) I did.
Thanks in advance
SerializationStreamFactory factory = (SerializationStreamFactory) GWT.create(MyClass.class);
What are you expecting this line to do? GWT will attempt to find a replace-with or generate-with rule that matches this class (either when-type-assignable or when-type-is), or failing that will attempt to invoke a zero-arg constructor on MyClass, effectively new MyClass(). Is this what you are expecting?
The selected exception you've pasted suggests that MyClass may not be on the source path that GWT has been given to compile from, but the full error log will provide more information.
It looks as though you are trying to mimic the generated RPC code, where a *Async rpc interface would be implemented by code that extends from com.google.gwt.user.client.rpc.impl.RemoteServiceProxy (which implements SerializationStreamFactory). That base implementation is extended further to initialize several fields such as the com.google.gwt.user.client.rpc.impl.Serializer instance, actually responsible for serializing and deserializing object streams.
Serializers are created (by default) from the base class of com.google.gwt.user.client.rpc.impl.SerializerBase, through the rebind class com.google.gwt.user.rebind.rpc.TypeSerializerCreator. If you've build your own generator for MyClass, you should be kicking this off to get the work done as ProxyCreator already should be doing.
Remember when building your own serialization/deserialization mechanism that you need to decide which types can be marshalled within this system - if you open it to all types, then you will need to generate FieldSerializer types for all possible objects on the source path. This will greatly expand the size of your compiled code.
If your main goal is learning how this 'magic' works, dig into the generators and associated code that live in the com.google.gwt.user.rebind.rpc package. There are other libraries that leverage these ideas such as the gwt-atmosphere project (see https://github.com/Atmosphere/atmosphere to get started). Also review the generated code that GWT creates when it builds a 'tradition' RPC interface.