GWT serialization issue while doing RPC - java

i am learning GWT.
I got a error regarding the serilizablity.
breif discription of my problem
In class Customproperties
package com.exp.shared;
import java.io.Serializable;
import java.util.List;
public class Customproperties implements Serializable {
private Object value;
private List<?> values;
// more variable
public Customproperties() {
// TODO Auto-generated constructor stub
}
public Customproperties(String propertyName, List<?> object,
String propertyType, boolean mulitiValued, String cardinality, Boolean required) {
this.propertyName=propertyName;
this.values=object;
// more initialization
}
public Customproperties(String propertyName, List<?> object, String propertyType,
boolean multiValued) {
this.propertyName=propertyName;
this.values=object;
// more initialization
}
public Object getValue() {
return value;
}
public List<?> getValues() {
return values;
}
}
In server package in one of the classImpl i am using a object of Customproperties
if (doc.getPropertyValue("cmis:objectTypeId").toString().equals("cmis:document")) {
customproperty=new Customproperties(p.getDefinition().getDisplayName(), p.getValue(), p.getType().toString(),p.isMultiValued());
}
else {
customproperty=new Customproperties(p.getDefinition().getDisplayName(), p.getValues(), p.getType().toString(),p.isMultiValued(),value.getCardinality(),value.isRequired());
}
here in if condntion p.getValue() returns Object.
and in else condition p.getValues() returns List.
in CustomProperties class when i change the object variable to string it is working perfectly fine.
but i dont change it it gives me error.
com.exp.shared.Customproperties' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = com.exp.shared.Customproperties#1aa5344
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619)
I dont want to change it String . i just want to receive Object. cause this object can be some times String, date, int.
Plzz help.

You should read the GWT docs about RPC serialization here.
The class java.lang.Object is not serializable, therefore you cannot expect that a collection of Object types will be serialized across the wire.
This is why you get your exception. In the code you've given, you're not using the field value. Both constructors on your class only set the values list. So if you're not using the field value, just remove it and it will work. But assuming that's a mistake and you do need to use it ...
You will have to know all the different possible types your value can have. And then either you have different fields, like intValue, dateValue, stringValue ...
Or you can have one String field, and serialize your objects into strings like this.
public class CustomProperties {
private String value;
private String type;
private void setValue(Object value, String type) {
if (value != null) {
this.value = value.toString();
this.type = type;
}
}
private Object getValue() {
if (value != null) {
if ("int".equals(type)) return Integer.valueOf(value);
elseif ("date".equals(type)) return // Parse date from value here
elseif ("string".equals(type)) return (String) value;
// other cases
}
return value;
}
}

In GWT when declaring containers never declare generic types like List.
Always use the more specific types like ArrayList.

In your case, the problem is most likely the List<?>. GWT doesnt know what possible types you are putting in that list, so instead of generating code to serialize every single possible type on the sourcepath, it generates nothing except for what it knows it already needs. When you attempt to put something in there that wasn't needed elsewhere, the exception occurs, indicating that GWT wasn't told that you planned on sending that object over the wire.
A standard approach here is usually to create a marker interface that probably implements Serializable, and make it a List<MyModelObjects>. Then every object that can fit in there should implement that interface.

Related

Is it possible to set a field's value instead of replacing the reference with a new object when Deserializing with Gson?

I'm currently using GSON to for my serialization library, and I'm having a some difficulty with figuring out how to read a value from the JSON and use it to update a field's value, without changing the reference of the field. I'll give a reduced example of my issue:
public static class Property {
String text;
public Property(final String text) {
this.text = text;
}
}
public static class Delegate {
final private Property property;
public Delegate(final Property property) {
this.property = property;
}
public String getValue() { return property.text; }
public void setValue(final String value) {
this.property.text = value;
}
}
public static class ExampleWithPropertyAndDelegate {
final Property textProp = new Property("Test");
final Delegate delegate = new Delegate(textProp);
}
So the way this works is that the delegate member of ExampleWithPropertyAndDelegate should always update the accompanied property member when setValue is called, e.g.
/* create the object we want to serialize/deserialize properly*/
var example = new ExampleWithPropertyAndDelegate();
/* setting the value via the delegate should update the underlying Property reference*/
example.delegate.setValue("Value Changed");
This example works exactly as expected when using the constructor. However, when deserializing, this no longer works. The underlying Property that the delegate references is no longer the same instance as the example.property member, that is example.property != example.delegate.property, even though it should.
I know this is happening since Gson uses the ReflectiveTypeAdapterFactory to actually set the object for the field, after construction. But is there a way to stop this from happening, say for any Property fields, instead of replacing them with a new instance via reflection, instead having it just set the value of the existing instance?

Java class method with Class and Field as parameters

How can i create a method that accepts Class and Field as parameters? Like this:
List<SomeClassEntity> list = ...;
// Service to make useful things around a list of objects
UsefulThingsService<SomeClassEntity> usefulThingsService = new UsefulThingsService<>();
// Maybe invoke like this. Did't work
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, SomeClassEntity::getFieldOne);
// or like this. Will cause delayed runtime erros
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, "fieldTwo");
public class SomeClassEntity {
Integer fieldOne = 10;
Double fieldThree = 0.123;
public Integer getFieldOne() {
return fieldOne;
}
public void setFieldOne(Integer fieldOne) {
this.fieldOne = fieldOne;
}
public Double getFieldThree() {
return fieldThree;
}
public void setFieldThree(Double fieldThree) {
this.fieldThree = fieldThree;
}
}
public class UsefulThingsService<T> {
public void makeUsefulThings(Class<T> someClassBClass, String fieldName) {
// there is some code
}
}
Want to have correct references on compile stage, not at runtime.
Update:
I need code that would look more convenient than this:
Field fieldOne = null;
try {
fieldOne = SomeClassEntity.class.getDeclaredField("fieldOne");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
usefulThingsService.makeUsefulThings(SomeClassEntity.class, fieldOne);
I apologize for the next clarification.
Update 2:
- The service compares the list with the previous list, reveals only the changed fields of objects (list items) and updates these fields in the objects in the original list.
- Currently i use annotation on entity's field that is actually ID of the entity and that ID is used to detect identically entities (old and new) when i need to update field of entity in source list.
- Service detect annotated field and use it for next update process.
- I want to refuse to use annotations and provide an Field directly in constructor of service. Or use something other that could establish a relationship between class and field on compilation stage.
Assuming that you want field access because you want to get and set the value, you’d need two functions:
public class UsefulThingsService<T> {
public <V> void makeUsefulThings(List<T> list, Function<T,V> get, BiConsumer<T,V> set) {
for(T object: list) {
V v = get.apply(object);
// there is some code
set.accept(object, v);
}
}
}
and
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldOne, SomeClassEntity::setFieldOne);
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldThree, SomeClassEntity::setFieldThree);
There are, however, some things open. E.g., how is this service supposed to do something useful with the field resp. property, without even knowing its actual type. In your example, both are subtypes of Number, so you could declare <V extends Number>, so the method knows how to extract numerical values, however, constructing an appropriate result object would require specifying another function argument.

Call method of unknown object

I have two ArrayLists - ArrayList1 and ArrayList2. Each of them is filled with objects - Object1 and Object2, respectively.
Both of these objects have method 'getText'.
Object1:
public String getText() { return "1";}
Object2:
public String getText() { return "2";}
At certain point I would like to loop through each of these lists using the same method (just with different parameter).
loopThroughList(1)
loopThroughList(2)
What is the syntax if I want to call a method, but I don't know which object it is going to be? This is the code I have so far:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getText());
}
It says Cannot resolve method getText. I googled around and found another solution:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
But this gives me NoSuchMethodException error. Even though the 'getText' method is public.
EDIT: To get the correct list, I am calling the method 'getList' of a different object (lists) that returns either ArrayList1 or ArrayList2 (depending on the provided parameter).
class Lists
public getList(list) {
if (list == 1) {
return ArrayList1;
}
else if (list == 2) {
return ArrayList2;
}
}
Define an interface for the getText method
public interface YourInterface {
String getText();
}
Implement the interface on the respective classes
public class Object1 implements YourInterface {
#Override
public String getText() {
return "1";
}
}
public class Object2 implements YourInterface {
#Override
public String getText() {
return "2";
}
}
Modify your getList method to return List<YourInterface>
public static List<YourInterface> getList(int list){
List<YourInterface> result = new ArrayList<>();
if(list == 1){
// your initial type
List<Object1> firstList = new ArrayList<>();
result.addAll(firstList);
} else {
// your initial type
List<Object2> secondList = new ArrayList<>();
result.addAll(secondList);
}
return result;
}
Declaration for loopThroughList
public static void loopThroughList(List<YourInterface> list){
list.forEach(yourInterface -> System.out.println(yourInterface.getText()));
}
Sample usage.
public static void main(String[] args) {
loopThroughList(getList(1));
loopThroughList(getList(2));
}
Interfaces work great here, but there a couple of other options if you're dealing with legacy code and cannot use interfaces.
First would be to cast the list items into their respective types:
for (Object o : lists.getList(listNumber)) {
if(o instanceof Object1) {
Object1 o1 = (Object1)o;
System.out.println(o1.getText());
}
else if(o instanceof Object2) {
Object1 o2 = (Object2)o;
System.out.println(o2.getText());
}
else {
System.out.println("Unknown class");
}
}
You can also use reflection to see if the object has a getText method and then invoke it:
for (Object o : lists.getList(listNumber)) {
try {
System.out.println(o.getClass().getDeclaredMethod("getName").invoke(o));
}
catch(Exception e) {
System.out.println("Object doesn't have getText method");
}
}
This is awful. Can you elaborate on what specifically you are trying to do? Java is strong typed by design, and you are trying to get around it. Why? Instead of Object, use the specific class, or interface as previously suggested. If that's not possible, and you must use lists of Objects, use instanceof and casting eg:
for (Object o : lists.getList(listNumber)) {
if (o instanceof Object1) {
Object1 o1 = (Object1) o;
System.out.println(o1.getText());
} else if (o instanceof Object2) {
Object2 o2 = (Object2) o;
System.out.println(o2.getText());
}
}
This is where interfaces come in.
interface HasText {
public String getText();
}
class Object1 implements HasText {
#Override
public String getText() {
return "1";
}
}
class Object2 implements HasText {
#Override
public String getText() {
return "2";
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2());
for (HasText ht : list) {
System.out.println(ht);
}
}
If one of your objects is not in your control you can use a Wrapper class.
class Object3DoesNotImplementHasText {
public String getText() {
return "3";
}
}
class Object3Wrapper implements HasText{
final Object3DoesNotImplementHasText it;
public Object3Wrapper(Object3DoesNotImplementHasText it) {
this.it = it;
}
#Override
public String getText() {
return it.getText();
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2(), new Object3Wrapper(new Object3DoesNotImplementHasText()));
for (HasText ht : list) {
System.out.println(ht);
}
}
Just to add more to this answer and give you some more to think on this (Will try to do it in a simple, non-formal way). Using interfaces is the proper way of doing such operation. However, I want to stand on the "bad idea":
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
What you are doing here, is using a mechanism called Reflection:
Reflection is a feature in the Java programming language. It allows an
executing Java program to examine or "introspect" upon itself, and
manipulate internal properties of the program. For example, it's
possible for a Java class to obtain the names of all its members and
display them.
What you actually attempted, is using that mechanism, to retrieve the method through a Class reflection object instance of your Class (sounds weird, isn't it?).
From that perspective, you need to think that, if you want to invoke your method, you now have, in a sense, a meta-Class instance to manipulate your objects. Think of it like an Object that is one step above your Objects (Similarly to a dream inside a dream, in Inception). In that sense, you need to retrieve the method, and then invoke it in a different (meta-like) way:
java.lang.reflect.Method m = o.getClass().getMethod("getText");
m.invoke(o);
Using that logic, you could possibly iterate through the object list, check if method exists, then invoke your method.
This is though a bad, BAD idea.
Why? Well, the answer relies on reflection itself: reflection is directly associated with runtime - i.e. when the program executes, practically doing all things at runtime, bypassing the compilation world.
In other words, by doing this, you are bypassing the compilation error mechanism of Java, allowing such errors happen in runtime. This can lead to unstable behavior of the program while executing - apart from the performance overhead using Reflection, which will not analyze here.
Side note: While using reflection will require the usage of Checked Exception handling, it still is not a good idea of doing this - as you practically try to duck tape a bad solution.
On the other hand, you can follow the Inheritance mechanism of Java through Classes and Interfaces - define an interface with your method (let's call it Textable), make sure that your classes implement it, and then use it as your base object in your list declaration (#alexrolea has implemented this in his answer, as also #OldCurmudgeon has).
This way, your program will still make the method call decision making at Runtime (via a mechanism called late binding), but you will not bypass the compilation error mechanism of Java. Think about it: what would happen if you define a Textable implementation without providing the class - a compile error! And what if you set a non-Textable object into the list of Textables? Guess what! A compile error again. And the list goes on....
In general, avoid using Reflection when you are able to do so. Reflection is useful in some cases that you need to handle your program in such a meta-way and there is no other way of making such things. This is not the case though.
UPDATE: As suggested by some answers, you can use instanceof to check if you have a specific Class object instance that contains your method, then invoke respectively. While this seems a simple solution, it is bad in terms of scaling: what if you have 1000 different classes that implement the same method you want to call?
your objects have to implement a common interface.
interface GetTextable {
String getText();
}
class One implements GetTextable {
private final String text;
public One(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
class Two implements GetTextable {
private final String text;
public Two(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
#Test
public void shouldIterate() throws Exception {
List<GetTextable> toIterate = Arrays.asList(new One("oneText"), new Two("twoText"));
for(GetTextable obj: toIterate) {
System.out.println(obj.getText());
}
}

Java - Using Generics to Create a Fluent Interface

In my current assignment, I have to build a new SchemaArtifact object filled with recursive Field objects (both custom classes) for a test case. I also need to do this using a fluent interface. The problem is that my build() function (pops up one level in the tree) should either return the root SchemaArtifact if the calling field is at the top level or return its parent if it is a child field. I know this might sound confusing, so hopefully some example code can clear it up:
public class SchemaHelper{
public SchemaArtifact makeSchema(){
return new SchemaArtifact()
.addField(new Field("FirstName"))
.addField(new Field("Nickname")).build()
.build()
.addField(new Field("LastName")).build();
}
}
public class SchemaArtifact{
private Map<String, Field> fields = new Map();
public addField(Field f){
this.fields.put(field.id, f);
return f;
}
}
public class Field{
public String id;
private Map<String, Field> fields = new Map(); //children
private Field parent; //null if parent is just the main schema
private SchemaArtifact schema; //schema that this Field belongs to
public Field(String id){
this.id = id;
}
public Field addField(Field f){
this.fields.put(field.id, f);
return f;
}
public <T> T build(){
if(this.parent != null){
return (T)this.parent;
}else{
return (T)this.schema;
}
}
}
As you can see, I tried using generics to return multiple types, but I get "The method addField(Field) is undefined for the type Object" when I try adding more than one Field at once. I also tried using a wrapper interface, which required needless casting later; and separate buildToSchema()/buildToField() methods, which works, but makes creating multiple schemas down the line more confusing.
With all that said, is there a way for me to get the singular build() method to return both a SchemaArtifact and a Field?
Thank you,
Tyler
The return type of build() must be known at compile time. In this case, the class of the returned object depends on a runtime condition, so it can't be known at compile time.
Two possibilities :
You know when to expect a Field or a SchemaArtifact. In this case you should use two separates methods and use them where appropriate.
You don't know what type to expect. In this case you should use an interface.
You could also to this :
Field field = new SchemaArtifact()
.addField(new Field("FirstName"))
.addField(new Field("Nickname")).build();
SchemaArtifactschema = field.build();
This will force the compiler to infer the right types, but it's the same as using two different methods, just less type safe (there will be a ClassCastException if you use the wrong type).

Map with custom value object

I want to have a Map object to contain specific value types.
Map<String,Object> foo = new HashMap<String,Object>();
foo.put("1",new Integer(1));
foo.put("2", new String("hello"):
for (Map.Entry<Integer, Integer> entry : foo.entrySet()) {
if(entry.getValue() instanceof String) {
//do something
}
else if(entry.getValue() instanceof Double) {
//throw Exception
}
}
You can see what i am trying to accomplish. I need specific Value types in my Map object so i don't have to put lots of if/else statements. How do i accomplish this ?
If you don't like the idea of having multiple maps, you can use the nice OOP feature called overriding.
see Override Methods for more information.
I would probably use composition pattern to wrap the value types and then define a interface for the action depending of the value types.
public abstract class ValueType {
public abstract void valueSpecificAction();
}
public class DoubleValueType extends ValueType {
private Double value;
public DoubleValueType(Double value) {
this.value = value;
}
public void valueSpecificAction() {
//do double specific actions
}
}
public class StringValueType extends ValueType {
private String value;
public void valueSpecificAction() {
//do string specific actions
}
}
You can then add the objects of type ValueType in the maps.
Map<String,ValueType> foo = new HashMap<String,ValueType>();
foo.put("key1", new DoubleValueType(42.0));
later you can get the value, which has the type ValueType with the public method valueSpecificAction() which do the stuff depending on the specific type.
I don't see how you can avoid to have an if-else somewhere in general.
Jan's solution would spare you the if-else only if the value types can be determine at compulation-time. That is the case in the toy example above but is it so in your actual problem?
If it is a matter of making the code look cleaner you can always hide the if-else and conversions in a set of private methods.

Categories

Resources