I've been using AutoBeans to map JSON data coming from a non GWT-RPC Java based web service. Everything has been working so far except for one mapping.
On the server side, the Class has a property of type Map where MyAbstractParentObject is the parent class of about 15 different child classes.
When I map that to a corresponding AutoBean interface on the client I'm not able to downcast MyAbstractParentObject to its child type after it's been decoded. I looked all over the GWT docs and 'the Googles' to see if AutoBeans even has polymorphic support but couldn't get an answer either way. Interceptors and Categories don't seem to be able handle this, just methods they want to exist in the interface that aren't getters/setters.
I was attempting to do a workaround using the type field in the JSON data to create an instance of the child class but the AutoBean does not give me access to the raw JSON, even though in the debugger I can see it as a protected field called 'data'. If I try to decode the original bean it will only have the fields in the MyAbstractParentObject.
The only alternatives I can see are to:
Extend or create my own AutoBeanCodex that can properly handle the
children of MyAbstractParentObject when it decodes the JSON.
Find a way to get to the raw JSON in the MyAbstractParentObject AutoBean
and use that to create and instance of the child class on the fly.
Switch to some other JSON-GWT Serialization framework like
GWTProJSONSerializer or piriti.
Any help would be appreciated.
I know this was asked a long time ago, but I struggled to find an answer too. I realized that the AutoBeans, since they're basically just fancy wrappers for the JSON, still contain all the data for the fields of the child object you want to downcast it to. So I wrote a method like this:
public <A, B> B cast( A sourceObject, Class<B> targetClass )
{
AutoBean<A> sourceBean = AutoBeanUtils.getAutoBean( sourceObject ); // Get the corresponding AutoBean.
HasSplittable splittableBean = ( HasSplittable ) sourceBean; // Implementation (if still AbstractAutoBean) supports this interface ;)
Splittable splittable = splittableBean.getSplittable().deepCopy(); // If you don't copy it, decode() tries to be clever and returns
// the original bean!
AutoBean<B> targetBean = AutoBeanCodex.decode( typeFactory, targetClass, splittable ); // Create new AutoBean of
// the target type.
return targetBean.as(); // Get the proxy for the outside world.
}
--Where typeFactory extends AutoBeanFactory, as you can see.
It's worked well enough for me. The trickiest bit was the cast to HasSplittable, since AutoBean doesn't extend that interface, but AbstractAutoBean (which implements AutoBean) does -- and a subclass of that is what's returned by calls to getAutoBean().
You also need to copy the Splittable, otherwise AutoBeanCodex thinks, "hey, I already have an AutoBean for that Splittable! Here you go!" -- and just gives you the original. ;)
Anyway, you can cast downwards, upwards...sideways! :P
Late edit: Stumbling upon this again months later, I figured I'd add a small caveat about something Jonathan mentioned below. The method I've described here is designed to be used on an AutoBean that hasn't been modified since it was deserialized. That's because (AFAIK) there's no guarantee that any setters you call will actually update the JSON (needed for the casting). This probably isn't a big deal, since typically you'll use this when you have an incoming DTO and you want to cast it to its real type ASAP, before doing anything else with it. In our case, none of our AutoBeans even had setters, so it wasn't really an issue. ;)
After you've cast it, you can do whatever you want with the resulting bean, which is fresh out of the factory after all!
I'm not very familiar with AutoBean but you probably can use the serializer/deserializer from RestyGWT. It supports polymorphism by making use of annotation.
link to the documentation:
http://restygwt.fusesource.org/documentation/restygwt-user-guide.html#Polymorphic_Sub_Types
Related
I can extend BaseDaoImpl using either Dao<InvoiceItem, Object> or Dao<InvoiceItem, UUID>, for instance. Why would I specify UUID when Object seems to work just as well?
Using Object in all of my Dao implementations in a large-ish project have been working so far. I thought I may have tripped over a case where it was breaking object cache functionality after enabling it, but my testing of the pattern used in ORMLite's ReferenceObjectCache.java to store and retrieve references from a Map showed that it works fine with either strongly typed keys or keys cast as Object.
I still haven't figured out why the object cache feature is not working for me after enabling it (same data, different objects), but trying to figure this out has me wondering why there is even a reason to specify the ID type in a ORMLite DAO to begin with.
I can extend BaseDaoImpl using either Dao<InvoiceItem, Object> or Dao<InvoiceItem, UUID>, for instance. Why would I specify UUID when Object seems to work just as well?
Dao is a generic class. Your question would be similar when you are talking about List<UUID> compared to List<Object>. The generic types mean that when you call dao.deleteById(uuid) it would provide type checking to validate that the id was the correct class. If you were using an Object id, you could inappropriately call dao.deleteById("hello") which would not find your object if the ID field was a UUID.
Also, if you call UUID id = dao.extractId(data), you don't have to cast the result because the compiler knows that the method returns a UUID.
Using Object in all of my Dao implementations in a large-ish project have been working so far.
The generic types are really only for the caller and provides compiler time type checking. Under the covers the ID type in the BaseDaoImpl is just an object.
Here's the tutorial from Oracle on why we use generics that might help your understanding. Their top reasons are:
Stronger type checks at compile time.
Elimination of casts.
Programmers can implement algorithms that work on collections of different types.
I'm doing a very simple thing that should just work, IMO. I've got a resource like:
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{nodeType}/{uuid}")
public Object getResourceInfo(#PathParam("nodeType") String nodeType,
#PathParam("uuid") String uuid,
#Context SecurityContext authority) { ...
Note I'm returning type Object. This is because depending on the call (here depending on the nodeType argument) I want to return a different concrete class (which will always be #XmlRootElement) and have that get marshalled out into the response.
However, this does not work. I get exception like:
Exception Description: A descriptor for class com.mycompany.XmlElementTypeInstance was not found in the project. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
If I change Object to a single subclass, it works. But I want it to be able to handle any subclass, XmlElementTypeInstance, XmlElementTypeInstance2, etcetc.
I tried making a common interface from which all of the XmlElementTypeInstance subclasses derive, but then I only get those properties in the interface, not the extra properties in the subclasses. Playing with #XmlElementRef and adding all possible properties to the common interface is extremely ugly and can't work quite correctly to generate the JSON I want, so please don't suggest that. =)
Is there any way to do this? It seems like simple, basic, necessary functionality... any other REST framework I've used, no problem...
The solution it turns out is simple (had to read the JSR instead of the actual Jersey docs, however!)
Instead of returning Object, returning Response (section 3.3.3 of JSR 339) with the object set as the entity forces the implementation to pick an appropriate MessageBody{Writer,Reader} at runtime.
return Response.ok().entity(<the object>).build();
Lost way too much time on this. Hope it helps someone later. =/
I am working with the HttpExchange class, and want to use the getAttribute function to get the POST parameters. If i just call the function and print the results it works. But there has to be some better way to access the returned object and get the contained data.
The Manual is here: http://download.oracle.com/javase/6/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/HttpExchange.html#getAttribute%28java.lang.String%29
How can i access the Object? Which methods does it have?
I am not familiar with this API, but it appears that HttpExchange.getAttribute is not the method you would use to get POST parameters. Rather it is a mechanism for sharing information within a chain of Filters. Since you would implement the Filters, you would document and understand the attributes that can be stored.
To read the POST details, wouldn't you do HttpExchange.getRequestBody?
Use Java Reflection. Using reflection you could do something like this
Class c = Class.forName("YourClassName");
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString()); //iterate through these methods to find out data
The HttpExchange returns you the type Object for the given attribute name, It is assumed that the one who try to retrieve the attribute knows the type of the attribute and can downcast the Object to appropriate class. E.g. -
String attrValue = (String) httpExchangeObject.getAttribute("nameOfTheAttribute");
you don't need to use reflection on the returned object to find out the structre.. I feel simple down-casting should solve the purpose.
I'm not familiar with this API either. The request POST parameters should be available in raw, unparsed form from getResponseBody(). However, if you know that the getAttribute method will contain the data you need, but you don't know which class it will have (I don't know how you would know the former without knowing the latter, but anyway), you can use reflection to print the name of the class:
System.out.println (foo.getAttribute("name").getClass ());
If it turns out to be an internal, undocumented class, you can then use more reflection (or other techniques) to look at the class hierarchy until you find a publicly-documented class or interface that you can use.
But this shouldn't be necessary because what you need should be documented somewhere.
Out of curiosity, I'd like to know if any class exists in Java with a method that returns a copy of its data structure. I ask because in class the teacher said a method like this breaks privacy, but I think that getting a copy of the structure is useful if you want to rearrange the structure. I'd like an example. Thanks.
I'm not entirely sure what you mean by the "data structure" of a class, but assuming you mean the members it contains, what you're looking for is reflection.
Try this tutorial.
Maybe you are missing the point: If you build a class which encapsulates some kind of internal data then you should NOT add a method which returns the internal data structure, but only the data that is encapsulated.
(Which is kind of the idea of encapsulation)
There should not be any need to "rearrange" your internal representation from the outside - because it is supposed to be internal and thus transparent in its use. (Meaning: You should not even be able to say what kind of data structure is used)
If you serialize it, any object (that is serializable) will happily prints its internal structure to a binary stream. And yes, this breaks encapsulation.
And yes, no one stops you from going to change the binary output and read it in again to create an altered object.
NB: there are more strange issues regarding serialization. For example, when deserializing objects new objects are created without their constructor ever being called. Et cetera. Serialization of objects is the maybe least object-oriented thing one can do with objects.
You're mixing up some concepts here.
Classes really are "data structures + methods", so in general you'd need a class to represent your class. Hey, a nice custom-built one would be the class your data is already in. You may be thinking of a class as a collection of simple fields, but this is not always the case.
As others have mentioned, you can extract the data via reflection, e.g.
public Map<String,Object> fields() {
Map output=new hashMap<String,Object>();
for (Field f:getClass().getFields())
{
try{
output.put(f.getName(), f.get(this));
}
catch(... //IllegalArgument, IllegalAccess.. {... }
}
return output;
}
You can get into encapsulation issues here, in general the class should provide the data that you need to see from it, I tend to use things like this only for debugging.
I'm not sure what you mean by "rearrange the structure". The class generally represents the structure of the data. If there's a transformation you want to accomplish, it probably belongs in a class method, e.g. are you thinking of something like a co-ordinates class that can provide a transformed version of itself into polar co-ordinates?
A simple way to see the internal representation of an object is to serialise it using XStream. This will generate an XML representation of the class and its components (and so on).
Does this break encapsulation ? Yes - in the sense that you're able to inspect the internal structure of the class. You can take that XML, change it, and provided that it matches the .class structure that it came from, deserialise it back into a .class instance.
For context, we are storing most of our data as JSON strings. This works very well with Hadoop on the backend and is easy to handle in Ruby on the front end. My data types fit the natural pattern for inheritance.
For simplicity, lets say I have a class Pet and a process FeedPet that feeds a pet. I also have a process WalkDog that only applies to Dog, which is a kind of pet. My data is organized such that I never need to worry about trying to walk a pet that isn't a dog.
What I would like to do is have Pet and Dog extends Pet, with Dog having an additional method "getLeash()", but I can't figure out how to map this to JSON.
Instead, I have a class Pet with a species data hashmap, so the WalkDog process would call pet.getSpeciesData("leash") instead of dog.getLeash().
I can create a Dog extends Pet, and I can serialize that to JSON using the Jackson library. The JSON object will have a leash field. But assume that I want to feed all the pets. All pets have a getFood() method. So the FeedPet process deserializes the objects to Pet. But this loses the leash field.
The WalkDog process can do this because it knows all of its input is going to be Dogs, so it can read it as a Dog and write it back out as a Dog.
Is there any way to serialize java objects to JSON such that I can preserve their type? I'm thinking something like Rails single table inheritance, but it would have to be something that the JSON libraries understand.
To make it work you must both embed some object type information in data (where it is only useful for deserializing) and usually use external schema definition which otherwise would not be needed (like XML Schema for xml; since that's basically a generic type system).
This has same problems as ORM has: Hibernate has to use ugly work-arounds (n+1 - way joins, "super tables" or discriminator fields).
Or another way to put it: data mapping/binding is not quite the same as object serialization/deserialization (latter tries to preserve more of object identity).
Here I am assuming that what you want is basically something like:
Pet pet = mapper.readValue(jsonString, Pet.class);
// (and possibly get an exception if Pet is an abstract class...)
Leash l = ((Dog) pet).getLeash();
If this is not the case, you could just simply bind to Dog
Dog dog = mapper.readValue(jsonString, Dog.class);
So anyway: Jackson project has feature request for doing just this, which allow you to do what (I think) you want.
However, this solution will mostly work for Java, as there is no standard way of passing Object type info within JSON. With XML this can sort of be done with XML Schema defined "xsi:type" attribute; which identifies Schema type, which is then mapped to class (yes, rather complicated way, but it does work).
UPDATE: Jackson 1.5 added support for this (i.e. implemented JACKSON-91 feature request), so it can be used for generating type identifiers, to allow proper handling of polymorphic types. It should work with non-Java systems too, given that you can fully configure details of how type information is to be included; and is NOT limited to using Java class names.
I've not had that much experience using JSON other than for fixtures in django, but in that instance I just have a "model" key, with the associated value.
It is then up to the program that is interpreting the objects to determine their type and inheritance hierarchy.
What I'm trying to say is that it is irrelevant what methods are available, as this doesn't need to be serialised. Only the object's name and attributes.
-- update
After reading your question again, it seems like your process is deserialising into the parent class, rather than the actual class. Since your dog class inherits from pet, you just want to make sure your deserialiser is creating objects of the most specialised class.
I don't know about the Jackson library, but if you can set it to have a type of model field, then that might be the go.