Class has two properties of the same name. Why does this happen? - java

I implemented a Java web service (JAX-RS API Jersey implementation). There is an entity:
#XmlRootElement
public class TestPhoto extends Photo {
public enum Type {
BEFORE, AFTER, ADDON
}
private User author;
#XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
private LocalDateTime createdTime;
private Type type;
public TestPhoto() {
super();
}
public TestPhoto(Long id, String key, String path, User author, LocalDateTime createdTime, Type type) {
super(id, key, path);
this.author = author;
this.createdTime = createdTime;
this.type = type;
}
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
public LocalDateTime getCreatedTime() {
return createdTime;
}
public void setCreatedTime(LocalDateTime createdTime) {
this.createdTime = createdTime;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
}
When I am trying to retrieve a list of such entities, I get an error:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 8 counts of IllegalAnnotationExceptions
Class has two properties of the same name "createdTime"
this problem is related to the following location:
at public java.time.LocalDateTime com.test.TestPhoto.getCreatedTime()
at com.test.TestPhoto
at public java.util.List com.test.TestAccount.getAddonPhotos()
at com.test.TestAccount
this problem is related to the following location:
at private java.time.LocalDateTime com.test.TestPhoto.createdTime
at com.test.TestPhoto
at public java.util.List com.test.TestAccount.getAddonPhotos()
at com.test.TestAccount
I know how to fix this. For instance, I could rename private fields and add _ as a prefix. Or I could add a #XmlAccessorType(XmlAccessType.FIELD) annotation to a field.
I see also, that there is something wrong with #XmlJavaTypeAdapter(LocalDateTimeAdapter.class) annotation. If comment it out everything works fine. But that part of functionality won't work in this case.
What I am trying to understand is why this happened in the first place. The code worked perfectly fine and then just stopped and started throwing such exceptions. Should this code have worked in the first place? Or is it completely wrong?

Related

Rest web services not returning XML response and even no log on console in eclipse

Creating an restful application but it is not returning the response in XML. Even there is no log on the console when hitting the URL "http://localhost:8080/message/webapi/messages".
I am returning a list and using #Produces(MediaType.APPLICATION_XML) to return the response in XML.
MessageResource.java
package org.porwal.restful.message.resources;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.porwal.restful.message.model.Message;
import org.porwal.restful.message.service.MessageService;
#Path("/messages")
public class MessageResource {
MessageService ms = new MessageService();
#GET
#Produces(MediaType.APPLICATION_XML)
public List<Message> getMessage(){
return ms.getAllMessage();
}
}
Message.java
package org.porwal.restful.message.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement( name = "Message" )
public class Message {
public long id;
public String message;
public Date created;
public String author;
public Message() {
}
public Message(long id, String message, String author) {
this.id = id;
this.message = message;
this.author = author;
this.created = new Date();
}
public long getId() {
return id;
}
#XmlElement (name = "ID")
public void setId(long id) {
this.id = id;
}
public String getMessage() {
return message;
}
#XmlElement (name = "Message")
public void setMessage(String message) {
this.message = message;
}
public Date getCreated() {
return created;
}
#XmlElement (name = "Created")
public void setCreated(Date created) {
this.created = created;
}
public String getAuthor() {
return author;
}
#XmlElement (name = "Author")
public void setAuthor(String author) {
this.author = author;
}
}
This is working if i do not use #XMLRootElement annotation and TEXT_PLAIN is returned well through the URL. I also tried to remove #XmlElement for each fields but no luck. When i remove #XMLRootElement then MessageBodyWriter error can be seen in logs on eclipse console but when includes #XMLRootElement then no logs on eclipse console and URL "http://localhost:8080/message/webapi/messages" throws the error:
Error in case of #XmlRootElement is missing.
org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo SEVERE: MessageBodyWriter not found for media type=application/xml, type=class java.util.ArrayList, genericType=java.util.List<org.porwal.restful.message.model.Message>. This exception comes only when i commented the line "//#XmlRootElement( name = "Message" )".
HTTP Status 500 – Internal Server Error
Can someone please tell what i am missing here?
You need to make all your fields in the Message class private. If you leave them as public, then JAXB will treat it as a property, and will consider it duplicate properties as you also haves JavaBean properties (getters/setters).
#XmlRootElement( name = "Message" )
public class Message {
private long id;
private String message;
private Date created;
private String author;
// ...
}
How I figured this out was by using a generic ExceptionMapper
#Provider
public class DebugExceptionMapper implements ExceptionMapper<Exception> {
#Override
public Response toResponse(Exception exception) {
exception.printStackTrace();
return Response.serverError().entity(exception.getMessage()).build();
}
}
You can register this with your application and it will catch unmapped exceptions and you can do whatever you want with it. Here we just print the stack trace. If we don't handle it, it will just get swallowed up and we will never know what happened.
When running the app with the ExceptionMapper, here's the error message I got.
Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 4 counts of IllegalAnnotationExceptions
Class has two properties of the same name "author"
this problem is related to the following location:
at public java.lang.String com.example.Message.getAuthor()
at com.example.Message
this problem is related to the following location:
at public java.lang.String com.example.Message.author
at com.example.Message
Class has two properties of the same name "created"
this problem is related to the following location:
at public java.util.Date com.example.Message.getCreated()
at com.example.Message
this problem is related to the following location:
at public java.util.Date com.example.Message.created
at com.example.Message
Class has two properties of the same name "id"
this problem is related to the following location:
at public long com.example.Message.getId()
at com.example.Message
this problem is related to the following location:
at public long com.example.Message.id
at com.example.Message
Class has two properties of the same name "message"
this problem is related to the following location:
at public java.lang.String com.example.Message.getMessage()
at com.example.Message
this problem is related to the following location:
at public java.lang.String com.example.Message.message
at com.example.Message
You can clearly see what the problem is. And aside from avoiding this error, this is how encapsulation is supposed to work anyway; the fields should be private and exposed via getters and setters.

Firebase No properties to serialize found on class

I'm bloqued creating a Firebase Database.
I'm trying to model a class. A very simple class:
package com.glups.model;
import com.google.firebase.database.IgnoreExtraProperties;
#IgnoreExtraProperties
public class AlumnoFB {
private String nombre;
private String apellidos;
private String telefono;
private String email;
private Boolean tieneWhatsapp;
private Boolean tieneTelegram;
private Boolean tieneHangouts;
private Long formaPago;
private Double ratioHora;
private Double precioHora;
private Double horasCompensadas;
public AlumnoFB() {
// Default constructor required for calls to DataSnapshot.getValue(User.class)
}
public AlumnoFB(String nombre,
String apellidos,
String telefono,
String email,
Boolean tieneWhatsapp,
Boolean tieneTelegram,
Boolean tieneHangouts,
Long formaPago,
Double ratioHora,
Double precioHora,
Double horasCompensadas) {
this.nombre = nombre;
this.apellidos = apellidos;
this.telefono = telefono;
this.email = email;
this.tieneWhatsapp = tieneWhatsapp;
this.tieneTelegram = tieneTelegram;
this.tieneHangouts = tieneHangouts;
this.formaPago = formaPago;
this.ratioHora = ratioHora;
this.precioHora = precioHora;
this.horasCompensadas = horasCompensadas;
}
}
that is almost like a sample class from Firebase.
Application user obtained from getUser() has been logged on Firebase.
When I call SetValue:
AlumnoFB alumno = new AlumnoFB("", "", "", "", false, false, false, ((Integer)FormaPago.INT_NO_PAGADO).longValue(), 0.0, 0.0, 0.0);
mDatabase.child("AlumnoFB").child(ControlClasesFirebase.getUser().getUid()).setValue(alumno) ;
A fatal exception raises.
06-10 10:17:37.179 13841-13841/com.glups.controlclases E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.glups.controlclases, PID: 13841 com.google.firebase.database.DatabaseException: No properties to serialize found on class com.glups.model.AlumnoFB
at com.google.android.gms.internal.zzaix$zza.<init>(Unknown Source)
at com.google.android.gms.internal.zzaix.zzj(Unknown Source)
at com.google.android.gms.internal.zzaix.zzaw(Unknown Source)
at com.google.android.gms.internal.zzaix.zzav(Unknown Source)
at com.google.firebase.database.DatabaseReference.zza(Unknown Source)
at com.google.firebase.database.DatabaseReference.setValue(Unknown Source)
at com.glups.controlclases.MainActivity$4.onClick(MainActivity.java:305)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5258)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I've checked types, and all are accepted. What's wrong?
Firebase require your Pojo to have public variables or getter/setter.
Change variable declarations to public
public String nombre;
public String apellidos;
public String telefono;
public String email;
public Boolean tieneWhatsapp;
public Boolean tieneTelegram;
public Boolean tieneHangouts;
public Long formaPago;
public Double ratioHora;
public Double precioHora;
public Double horasCompensadas;
If you are using proguard, some methods in the model could be stripped out depending on your configuration. As we know that there is no much optimization to POJO as it has only fields with getters and/or (optionally) setters, you can use the annotation "#Keep" so proguard will not delete any methods from this class.
Check this for more info: https://developer.android.com/studio/build/shrink-code.html
#Keep
public class Store {}
In my case I forgot to add a proguard rule to keep the model classes:
-keep class com.google.firebase.example.fireeats.model.** { *; }
This is same as #aselims's answer, just proguard version.
I found it in the official firestore example:
https://github.com/firebase/quickstart-android/blob/master/firestore/app/proguard-rules.pro
I have got this issue today and just resolve this providing getter/setter for private variables.
ex:
private String pid;
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
Now it's work perfectly without any error. Hope it will help newbies devs.
SOLUTION
In my case the issue was only in release/signed mode APK. So I fixed by doing these steps..
1- Added all model classes into proguaed rules like
-keep class com.YOUR_PACKAGE_NAME.modelClass.** { *; }
OR
#Keep
public class modelClass {}
2- Declared all variables of model class as private
3- Removed conflicting keys
Chill Pill :)
Verify this:
buildTypes {
release {
minifyEnabled false
...
}
debug {
minifyEnabled false
...
}
}
Declare variables as public.
public String email
In case anyone runs into this and none of the above solutions work, the variables declared also need to be of Object type and not raw types.
For example, you can use Integer's but you cannot use int's.
Same is true for boolean, float, double, etc. Basically, any unboxed type.
adding
#ServerTimeStamp
public Date date;
helped me to resolve the issue
You can do either of the two things -
Make your variables public
OR
Add getters and setters for all the variables
To solve the issue as mentionned below you should declare the class as Serializable and for the code :
`data class Review(
var rating:Float=0f,
var userId:String="",
var textR:String="",
#ServerTimestamp var timestamp: Date? = null
):Serializable{
constructor( rating: Float,userId: String, text: String):this() {
this.userId = userId
this.rating = rating
this.textR = text
}
}`
Try This Solution!
1- Implement Serializable interface
class model implements Serializable {}
2- Class Model with Private properties with Constructor and public setter and getter methods
public class Message implements Serializable {
#ServerTimestamp
private Date created;
private String content;
private String from;
private String to;
public Message(Date created, String content, String from, String to) {
this.created = created;
this.content = content;
this.from = from;
this.to = to;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
}
3- add this code in Proguard rules as said here
# Add this global rule
-keepattributes Signature
# This rule will properly ProGuard all the model classes in
# the package com.yourcompany.models.
# Modify this rule to fit the structure of your app.
-keepclassmembers class com.yourcompany.models.** {
*;
}

How do I create a compound unique index in Morphia/MongoDB Java?

Let's say I have a MongoDB Entity that looks as follows:
#Entity(value = "car")
public class Car {
public String manufacturer;
public String model;
public String year;
public Double price;
}
I would like to add an index such that the pair manufacturer,model,year is unique.
When I try the following annotation -- #Indexes(#Index(value="manufacturer,model,year, unique=true)) -- it works. But it throws the following error:
[WARN] (main) : DatastoreImpl - This index on 'Car' is using deprecated configuration options. Please update to use the fields value on #Index: #org.mongodb.morphia.annotations.Index(unique=true, dropDups=false, background=false, name=, value=manufacturer, model, year, expireAfterSeconds=-1, disableValidation=false, sparse=false, fields=[], options=#org.mongodb.morphia.annotations.IndexOptions(unique=false, dropDups=false, background=false, name=, expireAfterSeconds=-1, disableValidation=false, language=, languageOverride=, sparse=false))
How do I configure the index properly?
Try the following annotation
#Entity(value = "car")
#Indexes(#Index(fields = { #Field("manufacturer"), #Field("model"), #Field("year") }, options = #IndexOptions(unique = true)))
public class Car {
public String manufacturer;
public String model;
public String year;
public Double price;
}

How Do I Create this Nested Object?

So my front end colleague has successfully made this cool calendar using angular.uicalendar, that I'm trying to accommodate on the back end using java persistence and Spring MVC. The Calendar object itself has a lot of information and he's passing it as a nested object.
The parent object seems to have a “Start” and “End” which are LocalDateTimes, and a title which is a string. Then within that, there is an Email object (boolean sendEmail, int time (as in how long until you want it to be sent)) Then on that same layer there’s a text object which contains two variables that do virtually the same thing, but for texts, and also another called notification, which also does the same, but whether to post it on the website or not. Here's a screenshot of how it looks on the front end side if that helps.
Screenshot of Calendar Object
So I'm trying to replicate the object on my end so that I can store/edit the objects and I'm confused about how to proceed. My independent research suggests I can use an "#Embedded" annotation? One intriguing suggestion I had was "making the parameter into a Hashmap." Apparently Spring should be able to parse it into that if I don't have a special class prepared to store it. But I'm sure what that would look like. Could I even store the object in the database with this HashMap hanging off the end of it? Currently my calendarEvent class looks like so, and it's my attempt to make sense of what this Object would look like:
package com.theironyard.Entities;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* Created by macbookair on 12/16/15.
*/
#Entity
#Table (name = "events")
public class CalendarEvent {
#Id
#GeneratedValue
public int id;
#Column(nullable = false)
public LocalDateTime start;
#Column(nullable = false)
public LocalDateTime end;
#Column(nullable = false)
public String title;
//possibly use #Embedded here ?
public Object email() {
boolean send;
int time; // hours before sending email
return email();
}
public Object text() {
boolean send;
int time;
return text();
}
public Object notification() {
boolean send;
int time;
return notification();
}
public CalendarEvent(int id, LocalDateTime start, LocalDateTime end, String title) {
this.id = id;
this.start = start;
this.end = end;
this.title = title;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public LocalDateTime getStart() {
return start;
}
public void setStart(LocalDateTime start) {
this.start = start;
}
public LocalDateTime getEnd() {
return end;
}
public void setEnd(LocalDateTime end) {
this.end = end;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
So I guess in summary: What's the best way to store this object? Can I store the main object in the database with a HashMap hanging off of it?
Thanks everybody.

Generics in POJO - Is this a good practice

I have a Base Class.
#Data
class BaseDocument{
String id;
String name;
//Other fields
}
Say I have many classes that extends BaseDocument one below.
class NoteDocument extends BaseDocument{
String description;
Long lastModifiedDate;
//etc
}
It does not make sense to me to send entire document to UI in some cases. Most of the cases I need only id and name.
So for every document I have a VO class.
#Data
class BaseVO {
private String id;
private String name;
}
#Data
class NoteVO extends BaseVO{
//Nothing here now
}
And in NoteDocument I have.
public NoteVO getVo(){
Assert.notNull(getId());
NoteVO noteVo = new NoteVO();
noteVo.setName(getName());
noteVo.setId(getId());
return noteVo;
}
Now I have to copy this method in all the classes that extends BaseDocument.
Instead, I changed my BaseDocument like below.
#Data
class BaseDocument<V extends BaseVO>{
String id;
String name;
public V getVo(Class className) {
Assert.notNull(getId());
V vo = null;
try {
vo = (V) className.newInstance();
vo.setName(getName());
vo.setId(getId());
} catch (IllegalAccessException|InstantiationException e){
e.printStackTrace();
}
Assert.notNull(vo);
return vo;
}
}
I am new to generics. My first question, is this a good practice. Are there any problems in using reflection to create instance, any performance issues? Is there any better way to do achieve (write less code) this.
Edit: Suppose I need to display note in UI, Along with note I need to display name of the User who created note. I am using mongodb, when I save the note I also save UserVO in note, which will have user id and name of the user. If I save only user id while saving the note, I will have to do one more query to get the name of user while displaying. I want to avoid this.
Do not use reflection; use inheritance and maybe covariant return types instead. It will be faster, clearer, more precise, and easier to maintain. You may also find it useful to add methods to populate your VOs incrementally. I didn't come up with a clean way to apply generics to this situation, but I don't think you need them:
class BaseVO {
String id;
String name;
void setId(String id) {
this.id = id;
}
void setName(String name) {
this.name = name;
}
}
class NoteVO extends BaseVO {
// ...
}
#Data
class BaseDocument {
String id;
String name;
//Other fields
protected void populateBaseVO(BaseVO vo) {
vo.setId(id);
vo.setName(name);
}
public BaseVO getVO() {
BaseVO vo = new BaseVO();
populateBaseVO(vo);
return vo;
}
}
#Data
class NoteDocument extends BaseDocument {
String description;
Long lastModifiedDate;
// ....
protected void populateNoteVO(NoteVO vo) {
populateBaseVO(vo);
// ...
}
public NoteVO getVO() {
NoteVO vo = new NoteVO();
populateNoteVO(vo);
return vo;
}
}

Categories

Resources