I have a series of models, each of which has some properties that are used by a generator to generate getters/setters automatically (because there is some logic relating to default values contained therein and I don't intend to write these manually for models with 20 odd fields).
When I'm instantiating the model, I use GWT.create(...), but sometimes I have classes which refer to my model, and these don't know that the setters/getters exist, because they are generated.
For example, I have my model:
public class MyModel extends AbstractModel {
private Integer uid;
private String name;
// ...
}
public interface JsonBinder<MyModel> {
public void bindDataToMode(MyModel model, JSONWrapper json);
}
Now JsonBinder<T> is also a generated class using GWT.create, but it refers to MyModel and not the generated MyModelImpl. Therefore on compile I get errors like setUid(Integer value) is not defined for class MyModel.
Is there a way to have the compiler replace all uses of MyModel with MyModelImpl?
This applies to both generics and method arguments, return types, etc..
No.
In your specific case, I'd rather generate the MyModelImpl et al. upfront, using whichever code generator you want (including, for example, an annotation processor) and then code against the generated classes directly.
Related
In java it is possible to bound the generic parameter to classes implementing specific interface, so following is possible
interface MyInterface {}
class MyClassA implements MyInterface {}
class MyBoundedClassA<T extends MyInterface>
Now what if instead the interface I would like to bound the parameter to class annotated with specific annotation, like:
interface #MyAnnotation {}
#MyAnnotation
class MyClassB {}
class MyBoundedClassB<T extends MyAnnotation> // NOT possible
Is it possible to achieve such a behavoiur in Java?
---- EDIT
On request adding real world example. Slighly modifying the domain to make the example more understandable.
There is well known jackson library for serializing objects. This library does not support serialization of map keys other than Strings, so following is not possible out of the box
class TimeRange {
LocalDateTime startDate;
LocalDateTime endDate;
}
class SportsmenActivities {
private Map<String, <TimeRange, List<Activity>> sportActivities;
}
In this example the key of outer map is "sportsmanCode" liek "andy", "mike", "john" .Inner Map contains activities performed by given sportsman within given period.
So let's say Andy, was jogging for one day than the entry would be:
new SportsmanActivities().get("andy").put(TimeRange.of('2012-12-01,'2012-12-02'), List.with(new JoggingActivity)) // did some pseudo code here for readablity
Now as said Jackson will not serialize that out of the box, so I wrote generic module which allows serialization of such complex map.
To use that what you need to do is to annotate your "key" class like that:
#KeySerializable
class TimeRange {
#MyMapKey
LocalDateTime startDate;
#MyMapKey
LocalDateTime endDate;
}
As you can guess fields annotated with #MyMapKey will be used to generate MapKey.
Now I have a implementation of jackson class which dynamically serializes everything passed as a "text map key" annotated with #KeySerializable. The signature is follwing
class MyMapKeySerializer<T> extends JsonSerializer<T> {
serialize (T keyToSerialize) {
// do magic
}
}
This works, but I would like to limit T to only accept classes annotated with #KeySerializable, as only for such classes this method makes sense. Ideally this would be something like:
class MyMapKeySerializer<T annotatedWith #KeySerializable> extends JsonSerializer<T> {
serialize (T keyToSerialize) {
// do magic
}
}
If your goal is to assert only annotated classes are accepted then you have few workaround options:
Write an annotation-processor that does the assertion at compile time (see how #NonNull etc work). This is is interesting work but non-trivial as the compilation/type system is totally new to many seasoned Java devs.
Use some form AOP (AspectJ, Spring AOP etc) to "advise" all annotated methods with a Decorator whose responsibility is to assert the parameter has the same annotation.
Explicitly check at runtime using parameter.getClass().isAnnotationPresent(MyAnnotation.class)
A tool like the Checker Framework plugs into a compiler to restrict generic instantiation in a way similar to what you requested. It is implemented as an annotation processor, and it gives a compile-time guarantee of correct use.
For example, you can write class MyList<T extends #NonNull Object> {...}.
The Checker Framework enables you to build your own checker, which enforces any rules you like about #KeySerializable. In your case, the rules might be so simple that you can just define a couple of type qualifiers and use the Subtyping Checker -- at least at first.
Note that for the Checker Framework to work using the #KeySerializable annotation, that annotation must be a type annotation rather than a declaration annotation.
I have
class A
{
String a;
String b;
//..getters, setters
}
Now I have ArrayList<? extends Object> resultData holding objects of class A and some other classes.
Basically I need this list 'resultData' to generate a Json file in some other API.
Now my question is while adding the class A objects to the list & some condition(X) is true I need a modified class A object (or any other anonymous class object) like:
class A
{
String a;
//..getters, setters
}
that is one particular object of class A shouldn't have field String b (before criticising, I'm doing this because I need such modified object for my particular JSon format & I don't want to define a new class definition that is used only once)
my last option is to make anonymous class like this: (& then add it to my List)
Object ob = new Object{
String b;
//..getters, setters
}
Also pls. suggest any other method of creating anonymous class with required structure.
Java is not meant for changing classes or creating new classes at runtime.
It is possible with a lot of effort, like generating java bytecode on the fly using a bytecode library like BCEL(http://commons.apache.org/proper/commons-bcel/) or even generate .java files and run javac to generate bytecode.
You could simply use a hash map like Map<String,Object> that "simulates" an object that can receive arbitrary fields. If you really need totally configurable classes, I would go this way. Of course, you would not have nice getters and setters for each property.
But why would you need nice setters / a nice class anyway? As the structure of the class is determined at runtime, you can write no code that depends on this class, as you do not know how it will look like.
if i'm getting you correctly, you need to get rid off field for serialization, to json format,
if im right, then make your field transient
other solution is to make super class with field which you want to serialize,
and make A to extend it
but modifying class on fly, it is not right way to go
In my project I have a series of Models which basically just contain data, and have getters and setters for that data (which has to match an API). I am trying to use GWT generators to generate the getters and setters (because they have some logic in them for setting default values and I don't want to have this typed out all the time.
For example, MyBusinessModel.java:
public class MyBusinessModel extends AbstractBusinessModel {
private Integer uid;
private String name;
//... and so on
}
I then create a public abstract class AbstractBusinessModel which has some implemented base methods. I had created a generator for this, AbstractBusinessModelGenerator extends Generator, which automatically creates all the getters and setters, but I keep getting errors about MyBusinessModel not being able to be a superinterface of MyBusinessModelImpl (the generated class) because it's not an interface.
Is there a way for me to generate classes like this (I can't make MyBusinessModel an interface because I need it to have private properties), or can I only generate interfaces (which become classes)?
The answer is to use setSuperClass on the ClassSourceFileComposerFactory instead of addImplementedInterface. I didn't realise that this existed. Now I do.
I have a model object that's in fact an enum with fields and getters:
#Entity
public enum Type {
TYPE1, TYPE2, TYPE3, TYPE4;
#Column
private Long id;
#Column
private String name;
...
public String getName() {
return this.name;
}
...
}
It compiles and runs fine. However, if I call a getter method, it returns null (it doesn't load any values stored in the database). Is this the standard behavior? Is there a way to make JPA load them?
I'd say there is some misconception in this aproach:
Entities represent objects that can be stored in the database. In this case, the database (or any other persistent store) defines which instances are available.
Enums represent a fixed set of constants that are defined in source code. Thus the class itself defines which constants are available. In addition, it's generally bad practice to change the values of an enum, i.e. the name or id in your case.
You see that they are two quite different concepts which should be treated differently.
To store enums in entities (where the enum is a field of that entity), you could either use #Enumerated and store the name or ordinal of the enum, or (what we do more often) store one of the fields (we mostly use the id) and provide conversion methods.
If you want to store configurable "constants" in the database you might try and use plain entities for that, make the constructor private (Hibernate and other JPA providers should be able to deal with that) and provide an alternative implementation of the Enum class (you can't use the enum keyword though).
Have you looked into the #Enumerated annotation? I haven't ever tried to use it within an enum itself, however it works quit well binding a class property to an enum.
enum Type{TYPE1, TYPE2}
#Column(name="type")
#Enumerated(EnumType.STRING)
public Type getType(){return type;}
public void setType(Type t){type = t;}
If JPA cannot be made to handle this, you could add a public Type valueOf(long id) method to your enum class which you use as a factory to instantiate enum instances representing the values in your legacy table.
I have a class (for example District) that implements two Methods:
public Object getAtribute(String name) {
}
public void setAtribute(String name, Object value){
}
Everything is setup to call my Generator when GWT.create(Dirstrict.class) is called.
Now How can I modify the implementation of these methods in the same class(i.e write code inside them) so that the final code in District class will be like this:
public Object getAtribute(String name) {
//The generated code
}
public void setAtribute(String name, Object value){
//The generated code
}
Thanks,
Your generator won't be rewriting the implementation of the District class, it will be generating a subclass of District with a different implementation. That generated subclass is what will be returned by GWT.create(District.class).
Once your generated subclass is written, it will be compiled down to JavaScript and your original superclass implementation may be completely stripped out if it's never used, so the effect will be the same.
You have to create a generator class that extends com.google.gwt.core.ext.Generator and tell the gwt compiler to use your generator to generate the District class.
your.gwt.xml
<generate-with class="my.package.DistrictGenerator">
<when-type-assignable
class="my.package.District"/>
</generate-with>
But first you should think about if you really need to use a generator because it makes the code more complicated.