Java Nesting Ignore Inner Attributes - java

I have an object model that is handling relations between types. These references sometimes loop back around on themselves, and to stop that (in say a REST call) I am using things like the #JsonIgnore tag to make sure I don't get infinite nest recursion.
The issue with this is more a question of context. If I want an item to be included in one spot but not another (if being nested), #JsonIgnore stops it from both spots.
Example:
public class A implements Serializable{
Set<B> bs;
Set<C> cs;
...
}
public class B implements Serializable{
String name;
Set<D> ds;
...
}
public class C implements Serializable{
B b;
...
}
public class D implements Serializable{
...
}
If A is my main container which is transporting the objects. In the context of B as listed in A, I want the Set<D> to show. When an object B is used in context of C however, I want to hide Set<D> and only show the name.
If I were to mark #JsonIgnore on B.ds it wouldn't show up in either case. Is there some annotation/customization I can put on C.b to ignore inner attributes? #JsonIgnore("ds") or something? Is there another way to handle this entirely?

You can annotate the fields with #JsonView and then specify the serialization view you want to use in particular circumstances. Here's a post about using it with SpringMVC but the approach would be the same regardless.
So in your specific example,
public class View {
interface Full {}
interface Summary {}
}
public class B implements Serializable{
#JsonView({View.Summary,View.Full})
String name;
#JsonView(View.Full)
Set<D> ds;
}

Related

Mapping a Subclass to it's Parent Class

I have the following classes:
public class ParentClass implements Serializable {
private String field1;
private String field2;
public class ChildClass extends ParentClass implements Serializable {
private String field3;
private String field4;
In a service, I generate the ChildClass first, then I want to return only field1 and field2.
In order to achieve that, first, I tried to use modelmapper directly, using my autowired ModelMapper,
modelmapper.map(childClassInstance, ParentClass.class) but it generated an object of the ChildClass, which doesn't makes sense to me. I tried adding the TypeMap but I got
1) Converter com.sss.config.modelmapper.aaa.ClassesModelMapperConfig$$Lambda$1031/1744645655#28f3c1bf failed to convert com.sss.service.model.aaa.ChildClass to com.sss.swaggergen.model.ParentClass.
1 error
... 1024 common frames omitted
Caused by: org.modelmapper.MappingException: ModelMapper mapping errors:
Is there a way to solve this? I don't even need to use modelmapper for this and what I want is really just getting a subclass's in the context of a parent's class. So, I would be happy if I could just initate a ParentClass with a function such as:
final ParentClass initatedParent = chillClassInstance.isolateSuperClass() or something similar. I don't want to add constructors, so if there's no built in method to achieve this, I probably need to create a method that maps everything manually.

Add Java class to existing inheritance hierarchy in JPA with Hibernate

I have an abstract base class with existing subclasses that is mostly used for defining a number of common fields and associated methods. I have a separate concrete class that "organically evolved" (i.e., bad design due to unforeseen feature requests) to end up with all the same fields defined in that abstract subclass.
Is there any way of having that separate class extend the abstract class and carry over the data of existing stored instances of that separate class? I would like to use InheritanceType.SINGLE_TABLE, but if another strategy makes it easier or possible, I guess that's fine too.
Also, those are entities referenced in other entities (OneToMany). Is that a problem? Hibernate uses only one global sequence for assigning entity ids - so it should in theory be possible to not break those references even if the data is moved to another table, right?
Already tried a few things, but no luck so far (e.g., add the "extend" to the separate class, hard-code it to use the same table as the base class, manually add a field for the discriminator...).
I am also happy about any pointers to examples/docs on how to carry out class hierarchy changes and other data model changes with JPA/Hibernate without losing data!
So, here's a simplified example of the situation. Base is the abstract base class that already has sub-classes.
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#Table(name = "Base")
public abstract class Base {
private long persistenceId;
private String privateField;
#Id
#GeneratedValue
public long getPersistenceId() {
return persistenceId;
}
public void setPersistenceId(long persistenceId) {
this.persistenceId = persistenceId;
}
[...]
}
#Entity
public class SubclassToBe {
private long persistenceId;
private String privateField;
private String someFieldNotInBaseClass;
#Override
#Id
#GeneratedValue
public long getPersistenceId() {
return persistenceId;
}
#Override
public void setPersistenceId(long persistenceId) {
this.persistenceId = persistenceId;
}
[...]
}
The goal would be to have SubclassToBe inherit from Base, removing the definitions of shared fields but keeping the information stored there. And at the same time, not break references to the persistence ids of SubclassToBe objects that are used in other objects as part of OneToMany relations.

Need a confirmation regarding persisting a referenced (embedded) object using jdo+datanucleus

Hi I am persisting a class with a collection(List) of interface.
I see this on link
http://www.datanucleus.org/products/accessplatform_2_1/jdo/orm/embedded.html#Collection
and it says "Embedded elements cannot have inheritance (this may be allowed in the future)"
So, how to persist such objects?
I came accross the same issue a few hours ago, hope it helps others starting with jdo/datanucleus.
As stated in the current docs, the only way to persist a collection of interfaces is through an unidirectional join table. It's not possible to directly embed the objects implementing the interface.
#PersistenceCapable
public class SomeClass {
#Join
#Extension(vendorName="datanucleus", key="implementation-classes", value="ImplementingClass")
private List<SomeInterface> myList;
// this list would be embedded
private List<SomeOtherClass> myOtherList;
// ...
}
#PersistenceCapable
public interface SomeInterface {
// ...
}
#PersistenceCapable
public class ImplementingClass implements SomeInterface {
// ...
}
#PersistenceCapable(embeddedOnly="true")
public class SomeOtherClass {
// ...
}

JPA and generics

I'm wondering how an abstract class with generics would handle with JPA? I mean what kind of annotations do I need for the field?
Consider these:
#MappedSuperclass
public abstract class AbstractMyClass<T> {
// What about Strings and Integers? Do I need some kind of #LOB?
private T field;
public T getField() {
return field;
}
public void setField(T field) {
this.field = field;
}
}
And then these
#Entity
#Table(name = "String")
public class MyStringClass extends AbstractMyClass<String> {
}
#Entity
#Table(name = "Integer")
public class MyIntegerClass extends AbstractMyClass<Integer> {
}
JPA is perfectly able to handle your proposed, because the generic appears at the abstract class level and for your concrete classes it has exactly a single value per class. In fact, JPA will store your subclasses in one or more table, according to the #InheritanceStrategy you have chosen and uses different mechanism for that.
You can figure out yourself why your case is not a problem, reasoning about how an ORM could save the two classes on a DB:
You can store MyStringClass and MyIntegerClass in the same table, adding a Discriminator column so that the ORM, when it loads from the DB, know which constructor should be called.
You can store every subclass in more table.
What is not possible, on the other side, is to define a generic
#Entity
#Table(name = "MyGenericClass")
public class MyGenericClass<T> {
private T t;
public MyGenericClass(T t) {
this.t=t;
}
}
The reason for this is that, at compile time, the T is "erased" because of type erasure. It is used at compile time to verify signatures and correctness of types, but then it is turned into a java.lang.Object inside the JVM. If you follow until now, you should be able to understand the following:
In your case, every concrete subclass of AbstractMyClass has a type T which is defined for all instances of the class. While the T information is not retained into the AbstractMyClass, it is retained and unique inside the subclasses.
In the second case I posted, each possible concrete instance of MyGenericClass could have a possible different value for T, and because of type erasure this information is not retained.
*Note: the fact that the second case cannot be handled by JPA is absolutely reasonable and if you fall in that case you should ask yourself questions about your design. Generics are a great tool to design flexible classes which can handle other classes in a type-safe manner, but type-safe is a programming language concept which has nothing to do with persistance.
Extra : you could use javap to see what really is erasure. Take off annotations from MyGenericClass and compile it.
G:\>javac MyGenericClass.java
G:\>javap -p MyGenericClass
Compiled from "MyGenericClass.java"
public class MyGenericClass extends java.lang.Object{
private java.lang.Object t;
public MyGenericClass(java.lang.Object);
}
We can. if the T implements Serializable
#Entity
public class IgsSubject extends BasicObject implements Serializable{
private static final long serialVersionUID = -5387429446192609471L;
#MappedSuperclass
public class IgsBasicLog<T> extends BasicObject {
#ManyToOne
#JoinColumn(name = "ITEM_ID")
private T item;
#Entity
public class IgsLogA extends IgsBasicLog<IgsSubject> implements Serializable {
private static final long serialVersionUID = -8207430344929724212L;
}

Polymorphism in JAX-RPC web services

I have a JAX-RPC (Java) web service that needs to return a complex polymorphic value. To be more specific, the class structure is something like this:
abstract class Child {
}
class Question extends Child {
private String name;
// other fields, getters, and setters
}
class Section extends Child {
private String label;
private Child[] children;
// getters and setters
}
class Quiz {
private Child[] elements;
// getter and setter
}
My web service has a method that returns a Quiz, which of course may contain Questions and Sections which may contain Questions and other Sections, and so on and so forth. However, when I generate the WSDL, only Child and Quiz make it in. When I call the web service, I get back a Quiz element with the right number of children, but they're all Child elements, and they're all empty.
Is there a good way to make this work, short of just returning XML as a String?
Before anyone asks, due to circumstances beyond my control, I cannot use JAX-WS.
I don't think JAX-RPC supports polymorphism in that way. I had a similar problem, and had to work around it by creating a class that had just two members - one for each of the two classes that could possibly be returned - and only populating one depending on the type I wanted to return. So in your case:
class Child
{
private Section section;
private Question question;
// Constructor, etc...
}
class Question
{
private String name;
// other fields, getters, and setters
}
class Section
{
private String label;
private Child[] children;
// getters and setters
}
class Quiz
{
private Child[] elements;
// getter and setter
}
Which requires the client to check which member of child is populated, and is horribly ugly, I know.
Maybe someone is still looking for it, it can be done in axis 1.4:
Add next line into your section of axis web service deployment file (wsdd):
<parameter name="emitAllTypesInWSDL" value="true" />
Modify your task in ant build file to include 'extraClasses':
<axis-java2wsdl ... extraClasses="..."></axis-java2wsdl>
In extraClasses mention all classes which will be passed, since axis aren't able to guess which childs you'll be passing/returning as parameters.
Done, now you can pass derivated classes in methods accepts parent classes. Etc:
// server side class A { ...}
class B extends A {...}
class C extends A {...}
// ws
class wsAxis { public void processPolymorphCall(A obj); }
// client side
wsAxis.processPolymorphCall(new C());
// this will work now, as much as returning derivated classes in place of base class.

Categories

Resources