How to use JSON-B to serialize a transient property? - jax-rs

Given a
public class Foo {
private String x;
transient private String y;
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
}
How can you instruct JSON-B to serialise property y?
This is a case where type Foo is used in a JPA context (#Entity) where transient indicates a property should not be persisted.

Instead of using the transient keyword, annotate the field with the #javax.persistence.Transient annotation.
i.e.
#Transient
private String y;
Effectively this makes the property available to JSON-B for serialisation.

Related

Mapping DTO with final members in MapStruct

is there a way to map a DTO using MatStruct which have a few final data members as well and cannot have a default constructor , like :
public class TestDto {
private final String testName;
private int id;
private String testCase;
public TestDto(String testName) {
this.testName = testName;
}
public String getTestName() {
return testName;
}
public int getId() {
return id;
}
public String getTestCase() {
return testCase;
}
public void setId(int id) {
this.id = id;
}
public void setTestCase(String testCase) {
this.testCase = testCase;
}
}
please suggest how could this DTO be mapped using MapStruct.
You can use #ObjectFactory that would construct an instance of your DTO.
For example:
#Mapper
public interface MyMapper {
#ObjectFactory
default TestDto create() {
return new TestDto("My Test Name");
}
//the rest of the mappings
}
You can also enhance the #ObjectFactory to accept the source parameter, that you can use to construct the TestDto. You can even use a #Context as an Object Factory.
NB: You don't have to put the #ObjectFactory method in the same Mapper, or even a MapStruct #Mapper. You can put it in any class (or make it static) and then #Mapper(uses = MyFactory.class)

org.apache.avro.SchemaParseException: Undefined name:

For converting generics to avro schema i use the below annotation , but I get the exception after that
public class Test2<T>
{
#AvroSchema("{\"type\":\"array\",\"items\":[\"null\",\"Test4\"]}")
private Set<T> test4;
}
public class Test4 {
public Integer getX() {
return x;
}
public void setX(Integer x) {
this.x = x;
}
public Test4(Integer x) {
this.x = x;
}
public Test4() {
}
private Integer x;
}
The error I get here is
org.apache.avro.SchemaParseException: Undefined name:Test4
This thing worked
#AvroSchema("{\"type\":\"array\",\"items\":{\"name\":\"Child\",\"type\":\"record\",\"fields\":[{\"name\":\"x\",\"type\":\"int\"}]}}")
Thanks btw.

How do I map an Enumeration class without the discriminator being passed into the constructor?

Based on Jimmy's Enumeration classes idea I am wanting to see if I can avoid using the constructor to instantiate my type (which I assume is happening with the discriminator-value) but rather use a "factory method"-esque way of getting my instance mapped from the db.
Here is my type:
public class Impact : Enumeration
{
public static readonly Impact Carbon
= new Impact(1, "Carbon dioxide equivalent", CommonUnit.CO2e);
public static readonly Impact Energy
= new Impact(2, "Energy", CommonUnit.MJ);
public static readonly Impact Cost
= new Impact(3, "Cost", CommonUnit.Dollars);
public Impact(int index, string name, CommonUnit unit)
: base(index, name)
{
this.Unit = unit;
}
public CommonUnit Unit { get; private set; }
}
And here is the definition for Enumeration:
public class Enumeration : ValueObject
{
public Enumeration(int index, string displayName)
{
this.Index = index;
this.DisplayName = displayName;
}
public int Index { get; private set; }
public string DisplayName { get; private set; }
public override string ToString()
{
return this.DisplayName;
}
public static IEnumerable<T> GetAllFor<T>() where T : Enumeration
{
foreach (var publicStatic in typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
Enumeration item = null;
item = (Enumeration)publicStatic.GetValue(null);
yield return item as T;
}
}
public static T With<T>(int index) where T : Enumeration
{
return GetAllFor<T>().SingleOrDefault(i => i.Index == index);
}
}
ValueObject simply covers off Equality functionality.
Elsewhere I use the static methods to get items from this enum (kinda like how you could use the core Enumeration static methods):
impact = Impact.With<Impact>(index.ImpactId.Value);
This is pretty handy but I want to know if I can get NHibernate to do this too when rehydrating objects.
Can it be done and how?
With an NHibernate Custom Type:
public class EnumerationType<T> : PrimitiveType where T : Enumeration
{
public EnumerationType()
: base(new SqlType(DbType.Int32))
{
}
public override object Get(IDataReader rs, int index)
{
object o = rs[index];
var value = Convert.ToInt32(o);
return Enumeration.With<T>(value);
}
public override object Get(IDataReader rs, string name)
{
int ordinal = rs.GetOrdinal(name);
return Get(rs, ordinal);
}
public override Type ReturnedClass
{
get { return typeof(T); }
}
public override object FromStringValue(string xml)
{
return int.Parse(xml);
}
public override string Name
{
get { return "Enumeration"; }
}
public override void Set(IDbCommand cmd, object value, int index)
{
var parameter = (IDataParameter)cmd.Parameters[index];
var val = (Enumeration)value;
parameter.Value = val.Value;
}
public override string ObjectToSQLString(object value, Dialect dialect)
{
return value.ToString();
}
public override Type PrimitiveClass
{
get { return typeof(int); }
}
public override object DefaultValue
{
get { return 0; }
}
}
If you're doing an HBM.xml-based mapping, you can set the custom type like this:
<property name="Impact" column="Impact" type="Namespace.To.EnumerationType`1[[Impact, AssemblyWithDomainEnum]], AssemblyWithNHibCustomType"/>
Alternatively, if you're using Fluent NHibernate, you can create a convention to map all enumeration types without having to configure each one individually:
public class EnumerationTypeConvention : IPropertyConvention, IPropertyConventionAcceptance
{
private static readonly Type _openType = typeof(EnumerationType<>);
public void Apply(IPropertyInstance instance)
{
var closedType = _openType.MakeGenericType(instance.Property.PropertyType);
instance.CustomType(closedType);
}
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => typeof(Enumeration).IsAssignableFrom(x.Property.PropertyType));
}
}
And then add that convention however you like in your Fluent NHibernate configuration.
This seemed to work too, but perhaps Jimmy's way seems easier:
public class ImpactEnumType : IUserType
{
public SqlType[] SqlTypes
{
get
{
//We store our Impact in a single column in the database that can contain a int (for the index value)
SqlType[] types = new SqlType[1];
types[0] = new SqlType(DbType.Int32);
return types;
}
}
public Type ReturnedType
{
get { return typeof(Impact); }
}
public bool Equals(object x, object y)
{
// Impact is derived from ValueObject which implements Equals
return x.Equals(y);
}
public int GetHashCode(object x)
{
// as above
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
//We get the string from the database using the NullSafeGet used to get ints
int impactIndex = (int)NHibernateUtil.Int32.NullSafeGet(rs, names[0]);
// then pull the instance from the Enumeration type using the static helpers
return Impact.With<Impact>(impactIndex);
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
//Set the value using the NullSafeSet implementation for int from NHibernateUtil
if (value == null)
{
NHibernateUtil.Int32.NullSafeSet(cmd, null, index);
return;
}
value = (value as Impact).Index;
NHibernateUtil.Int32.NullSafeSet(cmd, value, index);
}
public object DeepCopy(object value)
{
//We deep copy the Impact by creating a new instance with the same contents
if (value == null) return null;
return Impact.With<Impact>((value as Impact).Index);
}
public bool IsMutable
{
get { return false; }
}
public object Replace(object original, object target, object owner)
{
//As our object is immutable we can just return the original
return original;
}
public object Assemble(object cached, object owner)
{
//Used for casching, as our object is immutable we can just return it as is
return cached;
}
public object Disassemble(object value)
{
//Used for casching, as our object is immutable we can just return it as is
return value;
}
}
My HBM XML:
<property name="Impact" column="ImpactIndex" type="namespace.childnamespace.ImpactEnumType, namespace.childnamespace" />

Jackson configuration to write enum as object

When I try to serialize and deserialize a Set<ClassA<?>> of generic objects that look as follows:
public class ClassA<T> {
private ClassB datum;
private T value;
...
}
If that T happens to be an enum, it gets written as a String value. This is fine for serialization, but when I deserialize, it's not possible to know if the String value is an enum or not. Jackson then turns the resulting object into a String and you get a ClassA<String> instead of ClassA<SomeEnumType>.
Is there a configuration in Jackson to have it create some hints that the value is an enum? Or perhaps turn the enum into a JSON object rather then a string value?
Is there a configuration in Jackson to have it create some hints that the value is an enum?
It's possible to deserialize to an enum instance from a matching JSON string value. Or is this somehow not applicable to your situation?
Here is an example.
import java.util.Set;
import java.util.TreeSet;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.type.TypeFactory;
public class JacksonFoo
{
public static void main(String[] args) throws Exception
{
ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
String myEnumJson = mapper.writeValueAsString(MyEnum.MyEnum1);
System.out.println(myEnumJson);
MyEnum myEnum = mapper.readValue(myEnumJson, MyEnum.class);
System.out.println(myEnum);
Set<ClassA<MyEnum>> set = new TreeSet<ClassA<MyEnum>>();
set.add(new ClassA<MyEnum>(new ClassB("bValue7"), MyEnum.MyEnum1));
set.add(new ClassA<MyEnum>(new ClassB("bValue8"), MyEnum.MyEnum2));
String setJson = mapper.writeValueAsString(set);
System.out.println(setJson);
TypeFactory typeFactory = TypeFactory.defaultInstance();
Set<ClassA<MyEnum>> setCopy = mapper.readValue(setJson,
typeFactory.constructCollectionType(Set.class,
typeFactory.constructParametricType(ClassA.class, MyEnum.class)));
System.out.println(setCopy);
}
}
class ClassA<T> implements Comparable<ClassA<T>>
{
ClassB datum;
T value;
ClassA()
{
}
ClassA(ClassB datum, T value)
{
this.datum = datum;
this.value = value;
}
#Override
public int compareTo(ClassA<T> o)
{
return 42;
}
#Override
public String toString()
{
return String.format("ClassA: datum=%s, value=%s", datum, value);
}
}
class ClassB
{
String bValue;
ClassB()
{
}
ClassB(String bValue)
{
this.bValue = bValue;
}
#Override
public String toString()
{
return String.format("ClassB: bValue=%s", bValue);
}
}
enum MyEnum
{
MyEnum1("myEnum1", 1), MyEnum2("myEnum2", 2);
String name;
int id;
MyEnum(String name, int id)
{
this.name = name;
this.id = id;
}
}
Output:
"MyEnum1"
MyEnum1
[{"datum":{"bValue":"bValue7"},"value":"MyEnum1"},{"datum":{"bValue":"bValue8"},"value":"MyEnum2"}]
[ClassA: datum=ClassB: bValue=bValue7, value=MyEnum1, ClassA: datum=ClassB: bValue=bValue8, value=MyEnum2]
If for some reason it's necessary to have enums serialized as POJOs, then it appears custom serialization processing is required. Serializing enums with Jackson

Problem with design in OOP (Virtual member call in constructor)

I am trying to achieve something like the following:
class Foo
{
public virtual int Number { get; set; }
public Foo(int n)
{
Number = n; //Virtual member call in constructor
}
public void Do() {
Console.WriteLine(Number);
}
}
class Bar : Foo
{
public override int Number
{
get
{
return x.Val;
}
set
{
x.Val = value;
}
}
Bar(int n) : base(n)
{
X x = new X();
x.Val = n;
}
public void F() {
x.Something(); //changes x.Val
}
}
The reason I am doing this is because I need to propagate the call to Do when called from a variable of type Bar.
Now, I can have objects that either inherit from Foo or Bar, thus Number needs to be the way it is now, ie directly expose the Val property of x. This is because I need to allow for the following code:
Bar b = new Bar(5);
b.F(); //changes the value of Val in x
b.Do(); //Needs to print the correct, modified value
The problem here is obviously in Foo, when assigning n to Number (Virtual member call in constructor) since x from the subclass would not have been initialized yet.
What do you think is a better way to structure such a design?
I can't use this current code because I am calling a virtual member from the constructor, which causes the Object Reference not set to an Instance of an Object exception since x in Number from Bar would not have been yet initialized.
My favorite quote:
Favor composition over inheritance
I would separate underlying data from operations:
interface IMyNumber
{
int Number { get; set; }
void Something();
}
class MyNumber : IMyNumber
{
public int Number { get; set; }
public MyNumber(int n)
{
Number = n;
}
void Something() {... }
}
class MyBoxedNumber : IMyNumber
{
int Number { get { ... } set {... } }
void Something() {... }
}
class Bar
{
private IMyNumber_foo;
Bar(IMyNumber foo)
{
_foo = foo;
}
public void F() {
_foo.Something(); //changes x.Val
}
public void Do() {
Console.WriteLine(...)
}
}