Can I refer to properties directly in entity constructor with EclipseLink? - eclipselink

EclipseLink version is 2.5.1
We've moved from GlassFish web-server to TomCat. This made us switch to static weaving because with TomCat dynamic weaving doesn't really work that easy.
Now that static weaving works, it seems to work quite a bit differently.
If I have an entity which sets some property directly in the constructor:
class Entity {
#Column
private String name;
public Entity() {
name = "something";
}
public String getName() {
return name;
}
}
Long story short this test will fail:
Entity e = new Entity();
assertEquals("something", e.getName()); // e.getName() returns null
This happens because getName(), after weaving, is not returning this.name anymore. Instead it calls a routing for initialization (if it's needed) and (I guess) gets the value of the property from some underlying HashMap.
But constructor is not being weaved, I even have looked into the sources of weaver and seems to be explicitly opting out of this:
/**
* Construct a MethodWeaver and allow it to process the method.
*/
#Override
public MethodVisitor visitMethod(int access, String methodName, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, methodName, desc, signature, exceptions);
if (!alreadyWeaved) {
// skip constructors, they will not changed
if (!"<init>".equals(methodName) && !"<cinit>".equals(methodName)) {
// remaining modifications to the 'body' of the class are
// delegated to MethodWeaver
mv = new MethodWeaver(this, methodName, desc, mv);
}
}
return mv;
}
The question is, maybe I miss something here? Is it the actual reality with EclipseLink 2.5.1 that you can't use properties directly in entity's own ctor? (and it's not even mentioned anywhere, not googlable at least)

It turns out yes, we can.
But there was a problem that led us to the property being not visible to the getter.
We actually have MappedSuperclass inheritance here and we were shadowing this field in the child class. Essentially this:
class A {
#Column()
protected String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class B extends A {
#Column()
protected String name;
// no #Override here
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
So we were just shadowing the property.

Related

Json Serialize an interface's properties which have non primitive types [duplicate]

With a simple class/interface like this
public interface IThing
{
string Name { get; set; }
}
public class Thing : IThing
{
public int Id { get; set; }
public string Name { get; set; }
}
How can I get the JSON string with only the "Name" property (only the properties of the underlying interface) ?
Actually, when i make that :
var serialized = JsonConvert.SerializeObject((IThing)theObjToSerialize, Formatting.Indented);
Console.WriteLine(serialized);
I get the full object as JSON (Id + Name);
The method I use,
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type _InterfaceType;
public InterfaceContractResolver (Type InterfaceType)
{
_InterfaceType = InterfaceType;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
//IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
IList<JsonProperty> properties = base.CreateProperties(_InterfaceType, memberSerialization);
return properties;
}
}
// To serialize do this:
var settings = new JsonSerializerSettings() {
ContractResolver = new InterfaceContractResolver (typeof(IThing))
};
string json = JsonConvert.SerializeObject(theObjToSerialize, settings);
Improved version with nested interfaces + support for xsd.exe objects
Yet another variation here. The code came from http://www.tomdupont.net/2015/09/how-to-only-serialize-interface.html with the following improvements over other answers here
Handles hierarchy, so if you have an Interface2[] within an Interface1 then it will get serialized.
I was trying to serialize a WCF proxy object and the resultant JSON came up as {}. Turned out all properties were set to Ignore=true so I had to add a loop to set them all to not being ignored.
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type[] _interfaceTypes;
private readonly ConcurrentDictionary<Type, Type> _typeToSerializeMap;
public InterfaceContractResolver(params Type[] interfaceTypes)
{
_interfaceTypes = interfaceTypes;
_typeToSerializeMap = new ConcurrentDictionary<Type, Type>();
}
protected override IList<JsonProperty> CreateProperties(
Type type,
MemberSerialization memberSerialization)
{
var typeToSerialize = _typeToSerializeMap.GetOrAdd(
type,
t => _interfaceTypes.FirstOrDefault(
it => it.IsAssignableFrom(t)) ?? t);
var props = base.CreateProperties(typeToSerialize, memberSerialization);
// mark all props as not ignored
foreach (var prop in props)
{
prop.Ignored = false;
}
return props;
}
}
Inspired by #user3161686, here's a small modification to InterfaceContractResolver:
public class InterfaceContractResolver<TInterface> : DefaultContractResolver where TInterface : class
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(typeof(TInterface), memberSerialization);
return properties;
}
}
You can use conditional serialization. Take a look at this link. Basicly, you need to implement the IContractResolver interface, overload the ShouldSerialize method and pass your resolver to the constructor of the Json Serializer.
An alternative to [JsonIgnore] are the [DataContract] and [DataMember] attributes. If you class is tagged with [DataContract] the serializer will only process properties tagged with the [DataMember] attribute (JsonIgnore is an "opt-out" model while DataContract is "op-in").
[DataContract]
public class Thing : IThing
{
[DataMember]
public int Id { get; set; }
public string Name { get; set; }
}
The limitation of both approaches is that they must be implemented in the class, you cannot add them to the interface definition.
You can add the [JsonIgnore] annotation to ignore an attribute.
I'd like to share what we ended up doing when confronted with this task. Given the OP's interface and class...
public interface IThing
{
string Name { get; set; }
}
public class Thing : IThing
{
public int Id { get; set; }
public string Name { get; set; }
}
...we created a class that is the direct implementation of the interface...
public class DirectThing : IThing
{
public string Name { get; set; }
}
Then simply serialized our Thing instance, deserialized it as a DirectThing, then Serialized it as a DirectThing:
var thing = new Thing();
JsonConvert.SerializeObject(
JsonConvert.DeserializeObject<DirectThing>(JsonConvert.SerializeObject(thing)));
This approach can work with a long interface inheritance chain...you just need to make a direct class (DirectThing in this example) at the level of interest. No need to worry about reflection or attributes.
From a maintenance perspective, the DirectThing class is easy to maintain if you add members to IThing because the compiler will give errors if you haven't also put them in DirectThing. However, if you remove a member X from IThing and put it in Thing instead, then you'll have to remember to remove it from DirectThing or else X would be in the end result.
From a performance perspective there are three (de)serialization operations happening here instead of one, so depending on your situation you might like to evaluate the performance difference of reflector/attribute-based solutions versus this solution. In my case I was just doing this on a small scale, so I wasn't concerned about potential losses of some micro/milliseconds.
Hope that helps someone!
in addition to the answer given by #monrow you can use the default [DataContract] and [DataMember]
have a look at this
http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx
Finally I got when it will not work...
If you want to have inside another complex object it will not be properly serialized.
So I have made version which will extract only data stored in specific assembly and for types which have the same base interface.
So it is made as .Net Core JsonContractResolver.
In addition to data extraction it solves:
a) camelCase conversion before sending data to client
b) uses top most interface from allowed scope (by assembly)
c) fixes order of fields: field from most base class will be listed first and nested object will meet this rule as well.
public class OutputJsonResolver : DefaultContractResolver
{
#region Static Members
private static readonly object syncTargets = new object();
private static readonly Dictionary<Type, IList<JsonProperty>> Targets = new Dictionary<Type, IList<JsonProperty>>();
private static readonly Assembly CommonAssembly = typeof(ICommon).Assembly;
#endregion
#region Override Members
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
if (type.Assembly != OutputJsonResolver.CommonAssembly)
return base.CreateProperties(type, memberSerialization);
IList<JsonProperty> properties;
if (OutputJsonResolver.Targets.TryGetValue(type, out properties) == false)
{
lock (OutputJsonResolver.syncTargets)
{
if (OutputJsonResolver.Targets.ContainsKey(type) == false)
{
properties = this.CreateCustomProperties(type, memberSerialization);
OutputJsonResolver.Targets[type] = properties;
}
}
}
return properties;
}
protected override string ResolvePropertyName(string propertyName)
{
return propertyName.ToCase(Casing.Camel);
}
#endregion
#region Assistants
private IList<JsonProperty> CreateCustomProperties(Type type, MemberSerialization memberSerialization)
{
// Hierarchy
IReadOnlyList<Type> types = this.GetTypes(type);
// Head
Type head = types.OrderByDescending(item => item.GetInterfaces().Length).FirstOrDefault();
// Sources
IList<JsonProperty> sources = base.CreateProperties(head, memberSerialization);
// Targets
IList<JsonProperty> targets = new List<JsonProperty>(sources.Count);
// Repository
IReadOnlyDistribution<Type, JsonProperty> repository = sources.ToDistribution(item => item.DeclaringType);
foreach (Type current in types.Reverse())
{
IReadOnlyPage<JsonProperty> page;
if (repository.TryGetValue(current, out page) == true)
targets.AddRange(page);
}
return targets;
}
private IReadOnlyList<Type> GetTypes(Type type)
{
List<Type> types = new List<Type>();
if (type.IsInterface == true)
types.Add(type);
types.AddRange(type.GetInterfaces());
return types;
}
#endregion
}

Why do I need to include #JsonProperty with my RestController

Rest Controller:
#RequestMapping(value = "/admin/rest/new-subscriptions")
public List<NewSubscriptionDTO> getNewSubscriptions() {
NewSubscriptionDTO dto = new NewSubscriptionDTO();
dto.setId("54");
dto.setName("John Doe");
return Arrays.asList(dto);
}
NewSubscriptionDTO:
package dermatica.web.admin.rx;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.joda.time.DateTime;
import java.io.Serializable;
public class NewSubscriptionDTO implements Serializable {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I get the following exception:
no properties discovered to create BeanSerializer (to avoid exception,
disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
If I annotate the fields with #JsonProperty it work fine.
Is there a way for the serialization to work automatically without needing this annotation?
#JsonProperty auto-generates a getter/setter that Jackson uses to read/write to the fields during serialization/deserialization. Here are some alternative approaches:
Provide your own public getters/setters for all fields
Make the fields public, generally frowned upon, but if you're creating a simple DTO, that may be acceptable.
Setting ObjectMapper Visibility for FIELD to ANY (see here)
Disable the FAIL_ON_EMPTY_BEANS exception (see here)
Given that your DTO class has getters and setters, this should work without #JsonProperty. I wasn't able to reproduce the exact error message you showed, but here are some suggestions that may help:
[Controller] Explicitly specify the method type as GET, either using method = GET or #GetMapping - not necessary, but it's good to be explicit
[Controller] Make sure you annotate the controller class with #RestController, indicating the response is serialized to JSON and wrapped in an HttpResponse object.
[DTO] You don't need to extend Serializable (see here).
The final controller would look like this:
#RestController
public class MyController {
#GetMapping(value = "/admin/rest/new-subscriptions")
public List<MyDTO> getDTO() {
MyDTO dto = new MyDTO();
dto.setId("54");
dto.setName("John Doe");
return Collections.singletonList(dto);
}
}
Response:
[{"id":"54","name":"John Doe"}]

Jackson deserialization issue with access modifier

Jackson throwing an exception in deserialization with protected access modifier.
I am trying to deserialize one object then accessing protected properties of parent class is throwing exception.
Class com.fasterxml.jackson.databind.deser.impl.FieldProperty can not
access a member "protected"
Make sure that Jackson can see protected fields. E.g.
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC;
#JsonAutoDetect(fieldVisibility = PROTECTED_AND_PUBLIC)
class Person {
protected String name;
}
Or define getters and setters as needed. E.g. :
class Person {
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

Expectations are not recorded for injectable instances

Here is my code and I am doing code coverage testing
public class RegisterTest {
#Tested Register register;
#Test
public void testGetStudentName(#Injectable final Student student) {
new NonStrictExpectations(){
{
student.getRollNo();
result="ab1";
}
};
assertEquals(register.getStudentNo(), "ab1");
}
}
I got assertion error for the above testcase because the injectable instance doesnt work here..I dont know y?
Here is my testclass...
Register.class
public class Register {
Student student=new Student();
public String getStudentNo(){
return student.getRollNo();
}
}
Here is my dependency class
Student.class
public class Student {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
How can I resolve that assertion error??
The #Injectable mock used in the test does work. However, it is never injected into the tested object, which instead creates its own Student instance. So, in situations like this you use #Mocked, not #Injectable.
I should point out two other things, though:
Please take notice of the API documentation. The JMockit jar files (even the Maven ones) contain source code precisely to facilitate access to API documentation from any Java IDE.
"Value classes" like Student (which merely contain getters/setters) are not good candidates for mocking. In general, they should not be mocked. Instead, real instances should be used.

Entity objects getters and setters for data properties

I recently started working in Java and was introduced to the wild and crazy world of getters and setters for everything. I hated it at first, but quickly got used to it. Too used to it.
I have been spending a lot of time lately thinking more about class design. One of the things I am trying to do is avoid the trap of doing getters and setters for everything. However, much of the work I do is with entities that are mainly data containers and I am not certain that getters and setters are actually inappropriate in these cases.
Here is a simple example using public properties.
class Space {
public String name;
public String description;
Space(final String name, final String description) {
this.name = name;
this.description = description;
}
}
Here is a simple example using private properties and using getters and setters.
class Space {
private String name;
private String description;
Space(final String name, final String description) {
this.name = name;
this.description = description;
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
public String getDescription() {
return this.description;
}
public void setDescription(final String description) {
this.description = description;
}
}
In these examples, both the name and the description fields should be able to be changed.
I feel like the getter/setter example is more clear and hides the implementation details of what name and description are. It would also allow for validation on set later if needed.
I have read several discussions about getters and setters being evil and/or an anti-pattern, but it really feels like those might not apply to this situation.
Maybe there are some options I have not yet considered. I'm open for suggestions!
The first version (public properties) is not a good idea. The second is better. As Josh Bloch would say, "favor immutability":
public class Space {
private final String name;
private final String description;
public Space(final String name, final String description) {
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
}
That being said, getters and setters tend to be overused.
You have heard the often oversimplified "get/setters are evil". Nobody (I hope) really means that there's anything wrong with it for data objects. I think the real idea is:
"Getters/Setters are evil, except for plain data storage objects" which itself is just an evangelism of "tell don't ask".
Ideally if a class has getters and setters, that's all it should have.
That's the argument anyway. I'm not sure I agree with it.
To put it simple:
You need getters for all fields that must be read from the outside.
You need setters for all fields that must be written from the outside.
This can be 100%, but most of the time it is less.
While the accessor pattern helps hide the implementation details of a class (e.g. using a hashtable to store attributes to save memory on sparsely used classes), it can be very verbose to implement (your example has 12 lines more with accessors). That's why C# has a special property syntax, which allows to concisely specify default accessors:
class Space {
public String Name { get; set; }
public String Description { get; set; }
Space(final String name, final String description) {
this.Name = name;
this.Description = description;
}
}
Alternative forms may add access specifiers and/or code:
private String _name;
public String Name {
get { if (_name == null) FetchName(); return _name; }
private set { _name = value; }
}