Java Class based on Enum fields - java

I'm dealing here with JWT and setting up custom fields.
All those custom fields are described in an Enum:
public enum JwtFields {
userId,
manyOtherCustomFieldsBellow,
blaBlaBla
}
So whenever I create token instead of passing strings for the keys, I'm using an enum as it is faster and safer.
Claims claims = Jwts.claims().setSubject(userId);
claims.put(JwtFields.someCustomFieldFromEnum.name(), "someValue")
Now, once I check that the received token is valid and all necessary custom fields are present, I want to deserialise it to some TokenDecoded class and attach it to the request payload, so whenever I'm processing a request I will have all values and fields from the JWT token.
However, that deserialise class pretty much contains all fields from the enum, and if tomorrow I will add new fields to the enum, I'll have to also manually update my TokenDecoded class to include that new custom field too.
The question:
How can I make this TokenDecoded class to be based on the enum fields, so if I add a new field to the enum, it will be automatically present in TokenDecoded? Is there reflection involved? Or it could be achieved simpler?

Lombok provides a feature that works the other way 'round: If you define your fields in a class, you can annotate it with #FieldNameConstants(asEnum = true) to generate an enum based on the field names. Or, without the asEnum parameter, you'll get public static final Strings for your fields if you only need it as Strings.

You have several options:
Use a Map instead of a class. Simplest solution but doesn't enforce typing or fields.
Code generation: you can generate the class at compile time (e.g. JavaPoet).
Byte code generation: you can generate byte code for the class at runtime (e.g. Javassist).
Use Groovy metaprogramming features (or any other JVM-based language that support runtime data structure definition).
In my opinion code generation at compile time is best suited to your scenario.
Note that if you're using JWT you might want to look into a JWT library instead of reinventing the wheel.

Related

How to make a data field optional (not required) in JAX-RS?

I have a RESTapi written using Jersey Framework. Along with it there is a POJO class. Now, my need is how do I make a particular field optional in my POJO so that the api will work regardless of that optional field? I want the API should work in both the cases, i.e
if I give that optional parameter then also,
if I don't give then also it should work.
Java 8's Optional was mainly intended for return values from methods, and not for data properties of Java classes(POJO), as described in Optional in Java SE 8:
Of course, people will do what they want. But we did have a clear
intention when adding this feature, and it was not to be a general
purpose Maybe or Some type, as much as many people would have liked us
to do so. Our intention was to provide a limited mechanism for library
method return types where there needed to be a clear way to represent
"no result", and using null for such was overwhelmingly likely to
cause errors.
The key here is the focus on use as a return type. The class is
definitively not intended for use as a property of a Java Bean.
Witness to this is that Optional does not implement Serializable,
which is generally necessary for widespread use as a property of an
object.
[credits] : https://blog.joda.org/2014/11/optional-in-java-se-8.html
I'm guessing you are referring to the serialisation of fields in your POJO. Since you have not stated which version of jackson you are using, you'll have to use one of these annotations to allow nulls:
Can be used on either class or getter:
#JsonInclude(Include.NON_NULL)
If you are using Jackson <2.x, use this:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

How to generate serialVersionUID-like id for a Java Class at runtime?

I'd like to generate an Id for a given Java Class by inspecting its field names, types, and all other components of the class that play a role during serialization and deserialization, not necessarily Java serialization as it could be Json, etc.
The id generation should be repeatable and deterministic unless there's a change in a field type or some other component of the class. I think I could recursively traverse the class and generate something like it but I didn't want to do it unless there's no other way.
I read that Java applies a complex procedure to determine serialVersionUID if none is declared. It considers class members, its super interfaces, etc. It seemed similar but I'd like to generate ids for non-Serializable classes as well.
My use-case is that I'm storing Java object(s) in an external datastore and I'd like to incorporate this runtime-generated id in the key to handle non-backward compatible changes gracefully.
You can get exactly the serialVersionUID of any class whether the field is present or not, via ObjectStreamClass.forName(String).getSerialVersionUID().

How to convert a Java object to key-value pair without using reflection

Is it possible to convert a plain Java Object with the usual getXXX and setXXX methods for its fields to a key-value pair, like Map<String, Object>?
I need to to this without relying on Java reflection, so it can be used with a Java-To-Javascript compiler like GWT.
GWT comes with a mechanism called Deferred Binding as a replacement for reflection. While normally you only use this API by calling GWT.create(Class<?>), it can also be used to write code generators that are invoked during the GWT compile process (i.e. the Java-to-Javascript translation).
You could use this to create a code generator that will output for any of your POJO classes
a helper class which would contain the toMap() and fromMap() methods. GWT offers an API that is kind of similar to Java's reflection API with classes like JClassType, JMethod, etc. These can be used to query classes (that you want to generate code for) for their getters and setters and generate the above-mentioned methods accordingly.
Your client code would then basically look like this:
Pojo1 pojo1 = ...;
// Pojo1Transformer is the class that is generated for your domain class Pojo1
Pojo1Transformer pojo1Transformer = GWT.create(Pojo1Transformer.class);
Map<String, Object> pojo1AsMap = pojo1Transformer.toMap(pojo1);
...
pojo1AsMap.put(Pojo1Transformer.NAME, "New Name");
Pojo1 changed = pojo1Transformer.fromMap(pojo1AsMap);
I've done this before by using a MapSerialisation interface:
interface MapSerialisation {
Map<String, Object> toMap();
void fromMap(Map<String, Object>);
}
Implement that on each of your model objects and use that for translation.
Another method I've used is Google Collections' Transformers, and having model transformation functions to convert between a Java object and a structure that Javascript would like.
I'd probably be tempted to use Jackson to serialise into JSON though.
Reflection is the most logical way to do this, some might argue that Class GetMethods / Fields are not technically reflection altogether.
One way to do this is to implement toHash() function where you could explicitly create a Hashtable / Map of your Object.

Java Builder generator problem

In a project of mine I have two packages full of DTOs, POJOs with just getters and setters. While it's important that they are simple java beans (e.g. because Apache CXF uses them to create Web Service XSDs etc.), it's also awful and error-prone to program like that.
Foo foo = new Foo();
foo.setBar("baz");
foo.setPhleem(123);
return foo;
I prefer fluent interfaces and builder objects, so I use maven / gmaven to automatically create builders for the DTOs. So for the above code, a FooBuilder is automatically generated, which I can use like this:
Foo foo = new FooBuilder()
.bar("baz")
.phleem(123)
.build();
I also automatically generates Unit tests for the generated Builders. A unit test would generate both of the above codes (builder version and non builder version) and assert that both versions are equivalent in terms of equals() and hashcode(). The way I can achieve that is to have a globally accessible Map with defaults for every property type. Something like this:
public final class Defaults{
private Defaults(){}
private static final Map<Class<?>, Object> DEFAULT_VALUES =
new HashMap<Class<?>, Object>();
static{
DEFAULT_VALUES.put(String.class, "baz");
// argh, autoboxing is necessary :-)
DEFAULT_VALUES.put(int.class, 123);
// etc. etc.
}
public static getPropertyValue(Class<?> type){
return DEFAULT_VALUES.get(type);
}
}
Another non-trivial aspect is that the pojos sometimes have collection members. e.g.:
foo.setBings(List<Bing> bings)
but in my builder I would like this to generate two methods from this case: a set method and an add method:
fooBuilder.bings(List<Bing> bings); // set method
fooBuilder.addBing(Bing bing); // add method
I have solved this by adding a custom annotation to the property fields in Foo
#ComponentType(Bing.class)
private List<Bing> bings;
The builder builder (sic) reads the annotation and uses the value as the generic type of the methods to generate.
We are now getting closer to the question (sorry, brevity is not one of my merits :-)).
I have realized that this builder approach could be used in more than one project, so I am thinking of turning it into a maven plugin. I am perfectly clear about how to generate a maven plugin, so that's not part of the question (nor is how to generate valid Java source code). My problem is: how can I deal with the two above problems without introducing any common dependencies (between Project and Plugin):
<Question>
I need a Defaults class (or a similar mechanism) for getting default values for generated unit tests (this is a key part of the concept, I would not trust automatically generated builders if they weren't fully tested). Please help me come up with a good and generic way to solve this problem, given that each project will have it's own domain objects.
I need a common way of communicating generic types to the builder generator. The current annotation based version I am using is not satisfactory, as both project and plugin need to be aware of the same annotation.
</Question>
Any Ideas?
BTW: I know that the real key point of using builders is making objects immutable. I can't make mine immutable, because standard java beans are necessary, but I use AspectJ to enforce that neither set-methods nor constructors are called anywhere in my code base except in the builders, so for practical purposes, the resulting objects are immutable.
Also: Yes, I am aware of existing Builder-generator IDE plugins. That doesn't fit my purpose, I want an automated solution, that's always up to date whenever the underlying code has changed.
Matt B requested some info about how I generate my builders. Here's what I do:
I read a class per reflection, use Introspector.getBeanInfo(clazz).getPropertyDescriptors() to get an array of property descriptors. All my builders have a base class AbstractBuilder<T> where T would be Foo in the above case. Here's the code of the Abstract Builder class. For every property in the PropertyDescriptor array, a method is generated with the name of the property. This would be the implementation of FooBuilder.bar(String):
public FooBuilder bar(String bar){
setProperty("bar", bar);
return this;
}
the build() method in AbstractBuilder instantiates the object and assigns all properties in it's property map.
A POJO is an object which doesn't follow the Java Bean spoec. ie. it doesn't have setters/getters.
JavaBeans are not required to have setters, if you don't want them to be called, don't generate them. (Your builder can call a package local or private constructor to create your immutable objects)
Have you looked at Diezel ?
It's a Builder generator.
It handles generic types, so it might be helpful here for the question 2
It generates all the interfaces, and implementation boiler plate based on a description XML file. You might be able, through introspection to generate this XML (or even goes directly into lower API )
It is bundled as a maven plugin.

Inheritance with JAXB

I have an XSD file which is used to generate some objects which are then shared with other systems. I'd like to customize some of the business logic a bit in there by making some more specific implementation of these. I'm not adding new fields which need to be serialized, but more along the lines of adding setMethods which may take different format parameters. These methods do the work of translating the data into a form which is needed by the underlying object.
I may have a field on the JAXB object which is a string, but my system gives me an integer. So, I want to handle the work of converting that in a class which extends my base class.
So, is there anything special you need to do in order to get JAXB to look for XmlRootElement on a subclass of the object you are asking it to serialize? Or must I include a #XmlRootElement attribute on my more specific class?
thanks!
Yes, #XmlRootElement/ #XmlType should be enough. But why don't you just add these methods to the generated classes? (in case you are not regenerating them on each build, which is wrong imo)
However I'd advice externalizing the conversion to other (converter) classes / methods.

Categories

Resources