i have a small code generation question.
I have a EJB3 backend that serves DTO objects to a frontend. The frontend uses a configurable binding procedure to map the attributes of the DTO to their forms.
At the moment they are doing it by specifing the attributes as strings in ther configuration. The binding implementation uses reflection to acces the attributes.
Sounds nice but the problem is, each time we change an attribute name in a DTO, this will not lead to a compile error in the frontend because they have just strings.
I'm now looking for a way to create a string constant for each attribute of the class that can be used by the frontend to map the attributes to their forms so that they get compile errors if i made changes in the dto attributes.
Example how it is:
public class CarDTO {
private String vendor;
private String name;
public String getVendor() {}
public String getName() {}
[..]
}
And how it should be:
public class CarDTO {
public static final String VENDOR = "vendor";
public static final String NAME = "name";
private String vendor;
private String name;
public String getVendor() {}
public String getName() {}
[..]
}
I was looking for a maven plugin that is capable of this but without success. Is there any one who nows a tool which can do things like that?
Thanks in advance
martin
Modifying existing class is more difficult then creating new one.
JPA took a interesting approach to solve this problem by creating CarDTO_ class. See http://www.hibernate.org/subprojects/jpamodelgen.html for more details. This approach is much easier. You can look at the hibernate maven plugin that implement the code generation.
If you really want to modify the existing class, then I would recommend using AspectJ with an approach similar to Spring Roo, where the aspect contains the generated code.
Edited (Example using AspectJ)
In this case, we are using AspectJ inter-type declarations that enables you to modify an existing class.
aspect CarAspect
{
public static final String CarDTO.VENDOR = "vendor";
public static final String CarDTO.NAME = "name";
}
Do implement this in maven, you need
a plugin to generate the CarAspect
the aspectj-maven-plugin to compile (weave) the aspect
Also, Eclipse has good support for AspectJ so you can use it there too.
I have a app with a similar frontend approach to access the domain classes, but I have my domain is entirely created via a DSL implemented via Eclipse Xtext, who can be used in a maven build also. There is a sample Java domain DSL project in the xtext distribution, its easy to start from there.
This sure is not a fast "just use a maven plugin" solution but once you get into Xtext it will pay off, especially if you have a lot domain classes, or a lot similar projects.
From my domain DSL I create via code templates and a xtext generator project three classes:
target/generated/mydsl (generated always):
AbstractDomainClass (in this file i have my static string's)
src/main/java (generated once):
ConcreteDomainClass
src/test/java (generated once):
ConcreteDomainClassTest
In the abstract domain class i have all getters and setters and simple persistence stuff in it, in the concrete domain class is the more complex stuff and the test class stands for it self.
Related
As I am gradually trying to remove Dependencies on Spring in the domain part of my library without minimal extra effort, I now turn to Spring Data and the Repositories
Originally we annotated our domain entities to look like this:
#Document
public void MyEntity {
#Id
#Getter private final EntityIdentifier identifier;
#PersistenceConstructor
public MyEntity( ... ) {}
...
}
and so on.
where #Document, #PersistenceConstructor and #Id originate from the Spring Project and some are for a specific database backend (MongoDB).
I would like to cut this dependency and use my own annotations, that make sense in my domain - #Document is definitly nothing my domain experts would understand when appearing on e.g an clas Chair or a Desk.
For de/serialization with Jackson, I can create mixins to add specific annotations to classes without modifying them in their origin.
Maybe there is a similar technique for Spring or some other way to achive this that is more elegant than creating a wrapping class?
Apparently I need some clarification:
Lets suppose we try to write a clean architecture application which consists out of the following modules: domain, adapters, application. In the domain module, I have my domain logic and domain entities and everything domainy. I do not have anything springy - no dependency on spring whatsoever, not even by having a dependency that somehow depends on spring.
In the adapters and application module, I do have dependencies on spring. I might use spring-data to implement the Repository-Adapters. I will use Spring to configure and glue together the application.
Now, in my domain module I have the following classes:
#AllArgsConstructor
#HashAndEquals(of="identifier")
#DomainEntity // <-- This is an Annotation that has no dependency on Spring!
public class DomainEntity {
#DomainId // <-- This is an Annotation that has no dependency on Spring!
#Getter private final DomainEntityIdentifier identifier;
#Getter #Setter private String someValue;
...
}
#HashAndEquals
#AllArgsConstructor
public class DomainEntityIdentifiers {
#Getter private final String name;
}
public void interface DomainEntityRepository {
DomainEntity findById(DomainEntityIdentifier identifier);
void save(DomainEntity domainEntity)
void deleteById(DomainEntityIdentifier identifier);
}
Now the task is, to provide the implementation of that interface in the adapters module, using Spring Data - e.g. spring-data-mongo and inject this adapter to the domain in the application module.
Now, surly I can create an class, lets say DomainEntityMongo which is basically the same as the DomainEntity just with the spring-data-mongo-annotations, then a public interface MyEntityRepository extends CrudRepository<EntityIdentifier, MyEntityMongo> and implement the interface DomainRepository by using MyEntityRepository and converting there and back again between DomainEntityMongo <=> DomainEntity.
What I am looking for is a more magical/generical solution. E.g.
Having jackson-style mixin-classes, which provide Spring with the necessary/missing meta-data to do the work
Configuring Spring to use non-spring-annotations to do the work (just as it is possible with the ComponentScan for non-component-inheriting Annotations)
Or - if the data guys have crafted another innovative solution - this innovative solution.
you can use
#JsonDeserialize(using = yourCustomizedDeserializer.class)
have a look here
https://www.baeldung.com/jackson-deserialization
you can customize your persistence strategy with #Persister. You may, for example, specify your own subclass of org.hibernate.persister.EntityPersister or you might even provide a completely new implementation of the interface org.hibernate.persister.ClassPersister that implements persistence via, for example, stored procedure calls, serialization to flat files or LDAP.
is that what you are looking for?
This morning I fell into a particular case that never happened to me before. I'm developing a Minecraft plugin using the minecraft server API which is usually called NMS with reference to the name of its packages (eg net.minecraft.server.v1_13_R1 for version 1.13).
The main problem with the use of the minecraft server API is that it is difficult to write a cross version code: indeed the name of the packages changes with each new version.
When the plugin only supports two versions it is usually easier to use the interfaces to write two different codes depending on the version. But when you have to support a dozen different versions (and this is my case), it's a bad idea (the plugin would be much too heavy, it would have to import every jar in the IDE, and I would have to redo the code with each new version).
In these cases I usually use reflection but I do not think it's possible here:
packet = packetConstructor.newInstance(
new MinecraftKey("q", "q") {
#Override
public String toString() {
return "FML|HS";
}
},
packetDataSerializerConstructor.newInstance(Unpooled.wrappedBuffer(data)));
As you probably guessed MinecraftKey is a class from NMS and I was told to use Java Dynamic Proxy API. I have never used it and would like to know if you would know a place that would explain to me how to do it simply? If you know of another better method that interests me too!
When I think about it, I think that this is really a lot of trouble for a tiny piece of code x)
EDIT :
My plugin uses the PacketPlayOutCustomPayload (aka plugin messages) to communicate with the mods of the players. It allows me to send a message (a byte []) on a particular channel (a String). But with the 1.13 this String has been replaced by a MinecraftKey (a wrapper for the String that replaces some characters and requires the use of a ":"). This poses a problem when players connect to 1.12 on my 1.13 server so I do not have a choice: I have to override the MinecraftKey object in this case.
I don’t really think using proxy classes is good solution here, it will only make it harder to debug, but if you need something like that you should use library like ByteBuddy: (as java can’t generate proxy for a class, only interfaces are allowed)
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.FixedValue;
import static net.bytebuddy.matcher.ElementMatchers.*;
public class Main {
public static void main(String[] args) throws Exception {
SomeKey someKey = new SomeKey("my", "key");
System.out.println(someKey); // :<
// this class should be cached/saved somewhere, do not create new one each time.
Class<? extends SomeKey> loaded = new ByteBuddy()
.subclass(SomeKey.class)
.method(named("toString").and(returns(String.class).and(takesArguments(0))))
.intercept(FixedValue.value("something"))
.make()
.load(Main.class.getClassLoader()).getLoaded();
someKey = loaded.getConstructor(String.class, String.class).newInstance("what", "ever");
System.out.println(someKey); // YeY
}
}
class SomeKey {
final String group;
final String name;
public SomeKey(String group, String name) {
this.group = group;
this.name = name;
}
public String getGroup() { return this.group; }
public String getName() { return this.name; }
#Override public String toString() {
return group+":"+name;
}
}
But I would just create separate modules in my project, one that does only work with real bukkit API and contains many interfaces to represent NMS types in some normalised and readable way.
And separate modules for each version, then you will not have much code to duplicate, as most of it will be abstracted and handled by that “core/base” module.
Then you can build it as one single fat jar or separate .jar per version.
Other solution might be using some template engines and preprocessors to generate java sources on build time, see how fastutil is doing this:
https://github.com/vigna/fastutil
And yet another solution for simple classes and parts of code would be to use build-in javascript or external script language like groovy to also create this pattern-line but in runtime. But I would use this only for simplest stuff.
Also for just using methods you can just use normal reflections.
You can also always inject into netty and instead of using default packet serializer just write own bytes, then you don't need that key at all.
My goal is to take a XML and/or XSD file and dynamically create a Java object that contains costume annotations and load it into the JVM. A 3rd party library would then look for those objects containing that annotation and perform some function to it. example output of what the java object would look like is as follows
import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.variable.PlanningVariable;
#PlanningEntity
public class NameAssignment extends ResourceAssignment{
private String name;
#PlanningVariable(valueRangeProviderRefs = { "PlannerCountRange" })
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The part i'm struggling with is generating the annotation fields #PlanningEntity and #PlanningVariable(valueRangeProviderRefs = { "PlannerCountRange" }) before, during or after the unmarshalling of the XML.
I've been trying to figure it out with JAXB, Dynamic JAXB, Dynamic JAXB, JavaAssist(for byte code manipulation), JCypher, and XJC(Just for compiling the classes). I even thought about dumping Java altogether and using Groovy.
I'm starting to feel like I'm over complicating this and need some guidance. This is a "from scratch" project so I have zero constraints on how I implement it.
Any Help would be greatly appreciated.
With jaxb2-annotate-plugin you may inject any static annotations into generated code just provide binding.
Please look for answer Custom annotation with jaxb2-annotate-plugin and XJC tool for details and examples how to use it.
How do I write a Java inner class with custom properties at compile time using annotations?
For instance, I want this :
#Generate
class Person {
String firstname, lastname;
}
to generate:
class Person {
String firstname, lastname;
public static class $Fields {
public static String firstname = "firstname";
public static String lastname = "lastname";
}
}
How can I write the interface:
#Retention(RetentionPolicy.SOURCE)
public #interface Generate {
// ...
}
I understand I need to do some kind of AST transformation to make this magical.
I am also aware of project lombok, but I want to know what the least common denominator is with a simple example, preferably within one method, and preferably something that a good editor would consider automatically, for instance RetentionPolicy.SOURCE for the javac compiler, which can be used in Intellij IDEA.
Project lombok is a beast code wise and is tough place to start.
It must be simpler than that, is it not?
Any ideas?
You can do this by reflection, but your new class won't be an inner class; but be warned, you will lose static type safety.
It can be done in 2 steps:
Read the annotated class via reflection and transform it into a String which represents the source code of your new class.
Write this string to file, compile this String using the Java compiler API and then load and instantiate the new class, all programatically; see exact steps here.
Alternatives to achieving similar functionality can also be obtained by bytecode instrumentation (see cglib or javassist) or maybe even with proxies.
Should a bean dto always have an associated interface ?
Below dto is used by jackson to send json over the wire :
public class Bean {
private String date;
public Bean(String date)
{
this.link = date;
}
public String getDate() {
return date;
}
}
Should this class always implement an interface to match its structure ?
I wouldn't unless you're using an API or Framework that requires an interface or are writing an API yourself.
Older versions of J2EE (before it became Java EE) required interfaces for enterprise beans, and some other frameworks use an interface to generate a proxy; however that has mostly been replaced by the runtime generation of synthetic proxies. If you start with a well defined class, you can later add an interface you discover a need for one.
Currently one of my tasks is maintaining an existing web application. Essentially everything in it has the Interface + Class pattern, but for no real reason as its all self contained. The extra files for the interfaces just clutter up the workspace and make tracking down the source of the actual code take a couple seconds longer in each case (can't just highlight and press F3 in Eclipse).