Will adding an annotation break Java Serialization? - java

I am in the process of rewriting a very old java app to Spring Boot and Hibernate 5. Part of this task requires that I replace our XML configuration (both Spring and Hibernate) with annotations.
I have the following question. Let's assume that the application contains a class as such:
public class MyObject implements Serializable {
private static final long serialVersionUID = 81848571841847187L;
private String id;
private String name;
//getters and setters...
}
This class Serialized across a network, and is included in a "common" jar, which classers must include, in order to deserialize on their end.
Let's assume that I add a few Hibernate and JPA annotations to the class
#Table(...)
#Entity
public class MyObject implements Serializable {
private static final long serialVersionUID = 81848571841847187L;
#Id
#Column(...)
private String id;
#Column(...)
private String name;
//getters and setters...
}
My question is: if the caller (who deserializes the above Object) does not have those annotations in his classpath, will serialization fail?

Only Annotations with RETENTION=RUNTIME used in byte code, but Serialization works with object fields, not with classes.
but its important to understand that Annotations can be used by custom serializer.
for example this is how #Transient exclusion is implemented.
so the next thing is to check what type of Serialization mechanism is used.
elad

Related

How to generate Entity classes from Java Model (dto) classes

I have a Java Bean class which has some attributes having some Object type as datatype. Again that Object is having attributes which is again have some Object datatype and so on...
public class MyService {
private String id;
private String href;
private Category category;
}
public class Category {
private String id;
private Type type;
}
public class Type {
private String id;
private SomeObject someObject;
}
so on ...
Now I want to create JPA Entity classes for the class MyService with all the Mappings (OneToMany etc.). I know from database table we can generate the Entity classes but can we do it from the Java bean classes?
Because if I do manually it will take much time. So please suggest if I can generate those Entity classes or some other alternative ways instead of manually creating those Entity classes.

Spring Data Rest nested property sort with JsonUnwrapped

So, I have this class, using #EmbeddedId and #JsonUnwrapped annotations
#Entity
class Order {
#EmbeddedId #JsonUnwrapped
private OrderPK pk;
private String field1;
private String field2;
//...getters, setters
}
And this is the primary key class
#Embeddable
class OrderPK implements Serializable {
private String orderNumber;
private String company;
//...getters, setters
}
I wanted to make Spring Data REST sorting treat the fields in the PK class as top-level instead of nested. Basically, I want to use this one: .../orders?sort=orderNumber,desc, instead of .../orders?sort=pk.orderNumber,desc. I couldn't find any way to do this in the documentations.
You can no longer achieve your goal, if you are using the #EmbeddedId option to implement your composite key. The reason is that the attributes under the hood of EmbeddedId class cannot be taken out as flat parameters.
Note that #JsonUnwrapped is not intended to perform that task.
You can use the following option instead of #EmbeddedId to achieve your goal.
Use #IdClass. Follow this example.

Convert Json Rest to Java DTO

is there a way that I can take the DTO's from a REST api? I want to create my DTO's automaticaly from the JSON REST api. Is there some way?
You can try use a framework library like RESTEasy (Jboss Suite) or Jersey or Gson
Then you only need define a estructure same a you class for example, if your class is something like:
#Entity
#Table(name = "\"entityName\"")
public class Entity implements Serializable {
private static final long serialVersionUID = 3469107762875646075L;
#Id
private Integer id;
#Column
private String name;
public Entity() {
}
//getters and setters
The interface will receive an object of that type.
#POST
#Path("/create")
#Produces(MediaType.APPLICATION_JSON)
Response createEntity(Entity entityObject);
And JSON be this way, then the conversion is automatic.
{
"id":"99",
"name":"stackoverflow"
}
NOTE: The information received must be of the same type defined in your Class to perform this conversion.
After some years, this is what I wanted:
https://app.quicktype.io/

Is there a way (e.g. an Eclipse plugin) to automatically generate a DTO from an Entity (JPA)?

I would like a plain forward DTO generation tool that would either
Generate it on the fly (e.g. cglib - create the class and DTO object on the fly)
Or an Eclipse plugin that will take the Entity and generate a DTO (user will specify which tree graph to include, and for non included, will include foreign keys instead of related entities etc)
E.g. take something like this
#Entity
#Table(name="my_entity")
public class MyEntity {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
#ManyToOne
private RelatedEntity related;
public RelatedEntity getRelated(){
return related;
}
...
And generate something like this :
#Entity
#Table(name="my_entity")
public class MyEntity imlpements MyEntityDTO {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
#ManyToOne
private RelatedEntity related;
//overrides MyEntity interface, it's allowed to narrow return type
public RelatedEntity getRelated(){
return related;
}
...
//implements MYEntityDTO respective interfaces
public Long getRelatedId(){return related.getId();}
And DTO interface(s):
public interface MyEntityDTO {
public String getId();
public String getName();
public Long getRelatedId();
public RelatedEntityDTO getRelated(); //RelatedEntity implements RelatedEntityDTO
...
}
public interface RelatedEntityDTO {
...
}
If we don't want to include children in the graph, remove it from the DTO interface:
public interface MyEntityDTO {
public String getId();
public String getName();
public Long getRelatedId();
...
I'm sure there is some eclipse plugn for it and if not, I challange someone to write one, or explain why what I want is not helpful (and provide an alternative suggestion)
Probably Hibernate Tools should be doing this: http://hibernate.org/subprojects/tools.html
Telosys Tools can generate both : JPA entity and DTO
Let's have a look at this tutorial https://sites.google.com/site/telosystutorial/springmvc-jpa-springdatajpa
it generates a full Spring MVC CRUD application with JPA
Architecture : https://sites.google.com/site/telosystutorial/springmvc-jpa-springdatajpa/presentation/architecture
The mapper Entity/DTO is also generated (it uses "org.modelmapper" )
The templates are customizable
Try to look at:
https://github.com/nikelin/spring-data-generation-kit
But it's only suitable for you if your project is under the
Maven control.

Storing Objects in columns using Hibernate JPA

Is it possible to store something like the following using only one table? Right now, what hibernate will do is create two tables, one for Families and one for people. I would like for the familymembers object to be serialized into the column in the database.
#Entity(name = "family")
class Family{
private final List<Person> familyMembers;
}
class Person{
String firstName, lastName;
int age;
}
This is an horrible design and I'm really not recommending it (you should just create another table) but it is possible.
First, you'll need to use a byte[] attribute to hold a serialized version of the list of persons that will be stored in a BLOB in the database. So annotate it's getter with #Lob (I would make the getter and setter private to not expose them). Then, expose "fake" getter and setter to return or set a List<Person> from the byte[]. I'm using SerializationUtils from Commons Lang in the sample below (provide you own helper class if you don't want to import this library) to serialize/deserialize on the fly to/from the byte[]. Don't forget to mark the "fake" getter with #Transcient or Hibernate will try to create a field (and fail because it won't be able to determine the type for a List).
#Entity(name = "family")
class Family implements Serializable {
// ...
private byte[] familyMembersAsByteArray;
public Family() {}
#Lob
#Column(name = "members", length = Integer.MAX_VALUE - 1)
private byte[] getFamilyMembersAsByteArray() { // not exposed
return familyMembersAsByteArray;
}
private void setFamilyMembersAsByteArray((byte[] familyMembersAsByteArray() { // not exposed
this.familyMembersAsByteArray = familyMembersAsByteArray;
}
#Transient
public List<Person> getFamilyMembers() {
return (List<Person>) SerializationUtils.deserialize(familyMembersAsByteArray);
}
public void setParticipants(List familyMembers) {
this.familyMembersAsByteArray = SerializationUtils.serialize((Serializable) familyMembers);
}
}
Don't forget to make the Person class Serializable and to add a real serialVersionUID (I'm just showing a default here):
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
// ...
private String firstName, lastName;
private int age;
}
But, let me insist, this is an horrible design and it will be very fragile (changing Person might require to "migrate" the content of the BLOB to avoid deserialization issues and this will become painful. You should really reconsider this idea and use another table for the Person instead (or I don't get why you use a database).
#Type(type = "serializable")
private List<Person> familyMembers;
if you can't use hibernate annotations try this:
#Lob
private Serializable familyMembers;
public List<Person> getFamilyMembers(){
return (List) familyMembers;
}
public void setFamilyMembers(List<Person> family){
familyMembers = family;
}
Annotate the property with #Column and define the type to be ArrayList, not just List. And make Person implement Serializable.
But you should do this only if your motives are very clear, because this is the correct solution in some very rare cases. As Pascal noted, if you ever have to change Person you'll have headaches.
You can create pseudoproperty (getter and setter) which accepts/returns the serialized form, and annotate the familyMembers with #Transient. This would also need to annotate the getters, not fields, for all other properties.

Categories