Using JAXB with JgraphX? - java

I have some entities mapped with JAXB annotations to turn them into xml, but within those entities mxCell there is an object, how can I map this object without adding annotations in the code library JgraphX​​?
There is my Objeto class:
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
#XmlSeeAlso({mxCell.class})
public abstract class ObjetoImpl implements Serializable, Objeto {
#XmlAttribute
protected String nome;
#XmlAnyElement
protected mxCell cell;
#Override
public String toString() {
return this.nome;
}
}
It's give me the following exception:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
com.mxgraph.model.mxICell is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at com.mxgraph.model.mxICell
at public com.mxgraph.model.mxICell com.mxgraph.model.mxCell.getParent()
at com.mxgraph.model.mxCell
at #javax.xml.bind.annotation.XmlSeeAlso(value=[class com.mxgraph.model.mxCell])
at ardis.model.conceitual.atributo.Atributo
at protected java.util.List ardis.model.conceitual.ObjetoWithAttributeImpl.attributes
at ardis.model.conceitual.ObjetoWithAttributeImpl
at ardis.model.conceitual.entidade.Entidade
at #javax.xml.bind.annotation.XmlSeeAlso(value=[class ardis.model.conceitual.entidade.Entidade])
at ardis.model.conceitual.ModeloConceitual
That exception occurs when the implementation of the interface is not correctly mapped with Jaxb, but i don't want enter into the jgraphx library and modify it

There are a couple of ways that you can handle this use case:
Option #1 - Specify the Impl Class with #XmlElement
For fields/properties that are of an interface type can use the #XmlElement annotation to specify the concrete implementation.
#XmlElemen(type=mxCellImpl.class)
protected mxCell cell;
For More Information
http://blog.bdoughan.com/2011/05/jaxb-and-interface-fronted-models.html
Option #2 - Use an XmlAdapter
An XmlAdapter allows you to convert an unmappable object to a mappable one during the marshalling/unmarshalling process. You could use this to convert JgraphX into your own domain object.
For More Information
http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html

I could not convert the objects of the program who had a mxCell inside using JAXB, so the solution for me was use the JgraphX "getXml" to convert the graph elements and the values of each cell. After that I get the value of the cells and use at my code.
The code to pass the graph to xml:
mxCodec codec = new mxCodec();
String xml = mxXmlUtils.getXml(codec.encode(graph.getModel()));

Related

Problem with Deserialization of Generic Classes

I came across a problem with Generics and Jackson recently and ended up with not using it.
I have an interface MonetaryType:
public interface MonetaryType implements Serializable {}
which is implemented by multiple enums like:
public enum IncomeType implements MonetaryType {
FULL_TIME_SALARY,
PART_TIME_SALARY,
CHILD_BENEFIT
}
public enum ExpenseType implements MonetaryType {
HEAT,
CONDO_FEES,
ELECTRICITY
}
I created a Generic Class:
public MonetaryValidation<T extends MonetaryType> {
private T monetaryType;
private boolean isPassed;
private String message;
// Getters and Setters
}
This object is not deserialized by Jackson library. Meaning that if any Spring REST endpoints are called while the payload contains MonetaryValidation object, it throws below exception:
java.lang.IllegalArgumentException: Cannot construct instance of
**.enumeration.MonetaryType (no Creators, like default construct,
exist): abstract types either need to be mapped to concrete types,
have custom deserializer, or contain additional type information
I do not want to solve the issue with Jackson polymorphic deserialization approach since it requires the client to pass an extra flag specifying the concrete implementation of the interface or abstract class, as far as I understood.
Unfortunately I ended up creating multiple sub classes of non-generic MonetaryValidation (one subclass per each MonetaryType subclass), which I know it is not a decent solution.
It is much appreciated if you could help me out to understand where the problem is and whether there is an approach to use #JsonSubTypes while passing an extra field is not needed.
There is an idea, try accept monetaryType as the String type parameter, and you can custom converter in the Generic class for handling the generic type field, such as:
public void setMonetaryType(String monetaryType) {
Optional<IncomeType> incomeType = Arrays.stream(IncomeType.values()).filter(i -> i.name().equals(monetaryType)).findFirst();
incomeType.ifPresent(i -> {
this.monetaryType = (T)i;
});
Optional<ExpenseType> expenseType = Arrays.stream(ExpenseType.values()).filter(i -> i.name().equals(monetaryType)).findFirst();
expenseType.ifPresent(i -> {
this.monetaryType = (T)i;
});
}
I think this is a simply way to achieve other than using JsonSubTypes or custom Converters, since it's really a generic parameter.

Should there be different wrap and unwrap class types when creating custom hibernate type class?

When I create a custom hibernate Type, such as
public class CustomHibernateType extends AbstractSingleColumnStandardBasicType<Custom>
{
public CustomHibernateType()
{
// Notice the JsonBinarySqlTypeDescriptor class from #vladmihalcea's hibernate types library
super(JsonBinarySqlTypeDescriptor.INSTANCE, CustomHibernateTypeDescriptor.INSTANCE);
}
#Override
public String getName()
{
return "CustomHibernateType";
}
}
And create the Type Descriptor
// only constructor for brevity, can include more if needed
public CustomHibernateTypeDescriptor()
{
super(Custom.class, ImmutableMutabilityPlan.INSTANCE);
}
I find that when I am saving and retrieving data in my custom hibernate type descriptor, the class type used is different. It is saved as a jackson JsonNode, which is expected as this is what is used in the JsonBinarySqlTypeDescriptor class, however when it is retrieved it is retrieved in the unwrap method as a PGobject (which has a simple string value).
Should I be expecting this, or should I be expecting JsonNode in both directions? I have no problems processing the PGobject, it just wasn't expected so I'm wondering if there is some config missing somewhere.
The wrap method transforms the entity attribute type to the one that should be passed to the JDBC PreparedStatement.
The unwrap method transforms the object that was extracted from the JDBC ResultSet to the expected entity attribute type.

Marshal an object as one of its properties with Jackson (as for value objects i.e primitive types wrappers)

EDIT: Previous answer does not work (it stills create a nested object)
I'm using Jersey and Jackson.
I got a class like
#XmlAccessorType(XmlAccessType.NONE)
public class Name {
private String value;
#XmlValue
public String getValue(){...}
public void setValue(String value){...}
}
used as in
public class Person{
#XmlElement(name = "IDName")
public Name getName(){...}
}
I'd like to marshal Name object as the value of it's identity property.
How can I achieve that?
<Person>
<IDName>foo</IDName>
</Person>
instead of
<Person>
<IDName>
<Value>foo</Value>
</IDName>
</Person>
I'd tried both to indicate in Person that Name object should be marshalled as itself.getValue() and either to indicate within Name class to marshal without any element wrapper (its fields directly) with no luck.
A possible solution is replacing #XmlValue annotation with Jackson's #JsonValue to make it work (tested).
I infer from http://wiki.fasterxml.com/JacksonJAXBAnnotations that it can be the only solution for now
According to this the official documentation
#javax.xml.bind.annotation.XmlValue
The field/property to which this annotation is applied will be named "value".
So maybe it's limited by design. Any better answer, specially if using JAXB annotations alone, will be much appreciated

Generate 1 dto to another dto convertor using freemaker. Stuck at the generating enum type1 to enum type2 convertor

I am using freemaker to generate dto convertor from one type to another. Defining things through custom annotations
E.g:
#CustomAnnotationTargetDTO(type=DTO2)
Class DTO1 {
#CustomAnnotationTargetProperty(propertyName="gender")
private String sex;
}
like this I have invented different annotations that I use to map a class and its properties to other type.
I now have a Enumeration in a DTO. Any idea on the similar lines that how i map 1 type to another.
I was thinking on the lines
#CustomAnnotationTargetEnum(xmlEnum="Type2Enum")
public enum Type1Enum {
#CustomAnnotationTargetEnumValue(enumValue="GIRL")
FEMALE(Byte.valueOf("1")),
#CustomAnnotationTargetEnumValue(enumValue="BOY")
MALE(Byte.valueOf("2"));
//other stuff below
}

#XmlJavaTypeAdapter and wrappers

I don't want use XmlJavaTypeAdapter annotations with XmlAdapter's class in my code directly.
So, I wrote some wrapper:
class BinderWrapper<MODEL, BEAN> extends XmlAdapter<BEAN, MODEL>{
private final Binder<MODEL, BEAN> target;
private BinderWrapper(Binder<MODEL, BEAN> target){
this.target = target;
}
static <MODEL, BEAN> BinderWrapper<MODEL, BEAN> createInstance(Binder<MODEL, BEAN> binder){
return new BinderWrapper<MODEL, BEAN>(binder);
}
#Override
public MODEL unmarshal(BEAN v) throws Exception {
return target.unBean(v);
}
#Override
public BEAN marshal(MODEL v) throws Exception {
return target.toBean(v);
}
}
that's wrappes my binders like XmlAdapter s. All my binders will implements Binder interface
public interface Binder<MODEL, BEAN> {
MODEL unBean(BEAN bean);
BEAN toBean(MODEL model);
}
But there is a problem. #XmlJavaTypeAdapter require XmlAdapter class without any wrapper. How I can solve this problem? - use other annotation / write some config / write some magic annotation /..
Thanks.
upd
I have model classes that aren't JavaBeans. So I want do some two step mapping : in beans and than into xml. I want do first step with annotations too. Probably I well need this beans not only for JAXB. The real question is : can I do first step with some non JAXB annotations?
I have model classes that aren't
JavaBeans. So I want do some two step
mapping : in beans and than into xml.
I want do first step with annotations
too. Probably I well need this beans
not only for JAXB. The real question
is : can I do first step with some non
JAXB annotations?
The XmlAdapter provides the two step mapping you are looking for. If you look at the example linked below Map is the object that is not a Java Bean. What the XmlAdapter does is convert it to a Java Bean that can be mapped.
You may find it easier to use the #XmlJavaTypeAdapter annotation at the type level rather than the property level. When used at the type level you are saying everyone that references that class should use the adapter instead of per property. See my post on JAXB and Immutable Objects for a type level example.
For more information see:
http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
http://bdoughan.blogspot.com/2010/12/jaxb-and-immutable-objects.html

Categories