Is it possible to persist a generic field?
I have this property on an Entity class
...
private T payload;
...
T extends EventMessagePayload
and
public interface StringPayload extends EventMessagePayload{
String getPayload();
}
In my application i persist the field only when is of String type and during the save operation all works great.
When I read the object instead JPA try to create a String object but instead is a StringPaylod. Is there a way to intercept the creation and handle the object marshalling?
JPA itself does not allow this, but your JPA implementation might allow it. We once did this with Hibernate, and it boilds down to implement your own EntityTuplizer (and a HibernateInterceptor to map your objects back to HibernateEntities).
We can. if the T implements Serializable
#Entity
public class IgsSubject extends BasicObject implements Serializable{
private static final long serialVersionUID = -5387429446192609471L;
Related
I have been using a Create Request as shown below and needed to implement an Update Request with some fields non-required.
#Data
public class CreateRequest extends BaseRequest {
#NotEmpty
private String token;
#NotEmpty
private String secret;
}
#Data
public class UpdateRequest extends BaseRequest {
private String token;
private String secret;
}
There are some relations and interfaces that should be used by both request. I think of using Template Design pattern by keeping the shared fields of these requests. Is that suitable for this scenario? Or, what would you suggest?
This may have been what you were getting at in your thoughts on the best approach, but I think your best bet is to have whatever fields/behavior are required for both request types in a shared parent class, and have their individual needs/different fields in a child class.
I am not sure exactly how your optional fields are meant to work conceptually, but if they are optional because of "default" values, then you can have the class with optional fields extend from the one with mandatory fields, and just implement a constructor which calls a super constructor with the default values. For instance if subClass extends parentClass and the constructor of the parent class is two strings, the second of which has a "default" in the child class, something like the following could be done:
public subClass extends parentClass {
subClass(String arg1) {
super(arg1, "default arg2");
}
}
I am building Spring Boot webflux REST API functionality that needs to work with data containing few Java type's (let's consider String, Integer, Double for example) information as part of JSON request/responses. Attribute representing Java type must be persistable inside mongodb as well (should not be problem once JSON can work with such attribute). I have following model class and type enumeration which is used by REST API to serialize/deserialize JSON message's.
#Getter
#ToString
#EqualsAndHashCode(exclude = "id")
#Document(collection = "core_scheme")
#JsonDeserialize(builder = SchemeModel.Builder.class)
#Builder(builderClassName = "Builder", toBuilder = true, setterPrefix = "with")
public class SchemeModel {
#Id
private final String id;
#Field(name = "userId") private final String userId;
#Field(name = "date") private final String creationDate;
#Field(name = "properties") private final Map<String, SchemeTypes> properties;
}
public enum SchemeTypes {
INTEGER, STRING, DOUBLE
}
Serialization and deserialization work's well. Now the problem is that when i want to resolve real Java type's stored inside Map<String, SchemeTypes> properties map i need to do mapping similar to this (just abstraction not real code):
SchemeTypes.INTEGER => Java Integer class
SchemeTypes.STRING => Java String class
SchemeTypes.DOUBLE => Java Double class
Is there any more simple way to represent Java type's stored inside model class and used within serialized/deserialized JSON file's so i can directly use it to deduce Java type without additional validation that it's valid Java type. For example if type's enumarated inside mentioned enum would have exactly same naming as real Java type's i could do following without any mapping:
public void deduceClass(SchemeTypes type) {
Class myClass = Class.forName(type.toString());
}
Note that i am looking for a solution which would work out of the box (i don't have to validate type's provided by user). If such solution would be harder to implement as mentioned mapping i will stick with mapping.
If you weren't saving this entity I could say you can actually directly map the SchemeTypes into corresponding class like following
public enum SchemeTypes {
INTEGER(Integer.class), STRING(String.class), DOUBLE(Double.class);
private final Class clazz;
private SchemeTypes(Class clazz){
this.clazz = clazz;
}
public Class getClazz(){
return clazz;
}
}
But as you are saving this it could cause some issue to deserialize.
Maybe you can save not the SchemaType instance directly but just the name of enum to overcome this like following
private final Map<String, String> properties;
and find the corresponding clazz value with a static method on this class like following
public static Class findClazzFor(String schemeTypeName){
return SchemeTypes.valueOf(schemeTypeName).getClazz();
}
Nevertheless I think cleanest solution would be keeping the SchemeType class instance mapping somewhere as a one-to-one map. And retrieve the corresponding class for provided schemeType as in the getClazz method above.
I need to understand if a transient variable inside a class that implements Parcelable interface should be read from the parcel in modelClass(Parcel parcel) method or written to the parcel in writeToParcel(Parcel parcel,int i) . Can anyone provide me with a class implementation with a transient variable in it. Thank you.
The "transient"-keyword has no effect on parcelable objects. There is no automation in reading and writing the fields in a parcelable object, so there is no ready made code that would take it into account. Any possible choice of special processing for transient fields is completely up to the person designing the class.
Specification (https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.3) says "Variables may be marked transient to indicate that they are not part of the persistent state of an object" so if you really want to go by the book you should not write them. But, as I said, since the reading and writing is done mechanically inside the class, the transient keyword doesn't make much sense.
class Employee implements Serializable {
private String firstName;
private String lastName;
private transient String confidentialInfo;
//Setters and Getters
}
You can simply add transient keyword before data type while declaring variable.
class Parcel implements Parcelable{
private Integer checkinId;
private transient String someCode;
//// some methods
}
interface Parcelable implements{
// some methods
}
I have problem, which I think can be easly solved, but I can't do it.
I have a class A and B and class A is stored in postgres db:
public class A() {
private B b;
...
}
public class B() {
private String firstName;
private String lastName;
private String personId;
private String userName;
}
In database, object of class b is stored as string userName in A entity. So to have object of class A from db in app, I have to read A record and create object of class B.
I want to create query with jooq, but jooq does not know how to convert this string username to instance of class B. How to tell jooq how it should map database A object to object of class A.
A class is equivalent to Person and B class is equivalent to Executor.
My query
return jooq.select()
.from(PERSON)
.where(PERSON.ID.eq(id))
.fetchOneInto(Person.class);
This is the exception thrown by my query
Caused by: org.jooq.exception.DataTypeException: Cannot convert from superadmin (class java.lang.String) to class fi.ssm.oksa.domain.person.Executor
at org.jooq.tools.Convert$ConvertAll.fail(Convert.java:1118) ~[jooq-3.8.5.jar:na]
...
I think I should use this http://www.jooq.org/doc/3.8/manual/code-generation/custom-data-type-bindings/ but I can't implement it.
There are different ways to solve this:
Use jOOQ's undocumented (as of version 3.8) nested record mapping feature
jOOQ has an undocumented feature in its DefaultRecordMapper that allows you to nest result records when you use any of the into(Class) methods. You have to manually specify the "path" of the nested record as if you were actually using ORDBMS nested records, as such:
jooq.select(
PERSON.FIRST_NAME.as("executor.first_name"),
PERSON.LAST_NAME.as("executor.last_name"),
PERSON.PERSON_ID.as("executor.person_id"),
PERSON.USER_NAME.as("executor.user_name"))
.from(PERSON)
.where(PERSON.ID.eq(id))
.fetchOneInto(Person.class);
When you alias your columns this way, then the DefaultRecordMapper will search for the executor property in the Person class, and put the trailing sub-path into a nested object.
In this example, I'm going to assume the slightly modified versions of your classes:
// instead of A
public class Person {
private Executor executor;
...
}
// instead of B
public class Executor {
private String firstName;
private String lastName;
private String personId;
private String userName;
}
Override the DefaultRecordMapper
You can implement your own algorithms for mapping when using the into(Class) methods as documented here:
http://www.jooq.org/doc/latest/manual/sql-execution/fetching/pojos-with-recordmapper-provider
Use an explicit record mapper:
Of course, nothing forces you to rely on jOOQ's built-in automatic mapping features. You could write your own algorithm like this, for instance:
jooq.select()
.from(PERSON)
.where(PERSON.ID.eq(id))
.fetchOne(r -> new Person(new Executor(r.get(PERSON.FIRST_NAME), ...));
I have a serializable class that extends Servlet
public class FileDownload extends HttpServlet{
#SuppressWarnings("compatibility:6754389671327954013")
private static final long serialVersionUID = 1L;
private ResultSet rset;
......
}
My Question is:
Is the rset object automatically converted as transient at compile- or run-time? or do I have to mark it explicitly as transient? (That is a warning brought up from my IDE JDeveloper).
No, the field is not neglected by serialization - you'll get a java.io.NotSerializableException if you try to serialize an instance of FileDownload. Mark it transient. Btw, what is a ResultSet doing as a field in a Servlet? This is not thread-safe. ResultSets should be local variables only, in any context.
You have to call transient your own.But you cannot serialize an object unless it implements Serializable interface.ResultSet is such kind of object.