I am looking to go from using POJOs to enums. One thing that's in my way is hibernate validation. I have been looking up how to apply validations to enum classes, but at most I am finding information on how to validate an enum property of a POJO, which is not what I want.
An example of the enum class I want to validate is;
EMAIL("email","v1",STRING),
FIRST_NAME("firstName","v1",STRING),
LAST_NAME("lastName","v1",STRING),
AGE("age","v1",INTEGER)
I haven't seen of or heard of using annotations on enums, but is there a way to write a custom validator that will check each enum and make sure its not null and is of the correct type?
The enums will not be saved to the db, they will be parsed and transferred to another service that will then save it to the db. I would parse first then validate but the way the code is written, this can't be done. I want to validate that the enums are meeting the db constraints
Related
In GraphQL Java implementation's document, type wiring is done as below, which contains one for the human query and one for the friends field of the Human type as highlighted.
I am wondering what is the use of the latter, the one for the friends field of the Human type.
I think we already return the a whole Human object, including the friends field, in the former type wiring using the StarWarsData.getHumanDataFetcher(), then why we need the latter?
Thanks!
The schema is as below:
The friendsfield is of type Character[]. When you return a certain type, fields that aren't of a built-in scalar type (such as String, which is built-in, vs. Character which isn't) require their own fetcher in order to be retrieved. You can, however, define a DTO that models the Human type and the smart graphql.schema.PropertyDataFetcher provided by graphql-java should retrieve the fields of your POJO, since it knows how to follow POJO patterns based on the field name.
One of my goals is to create an engine that will set values in pojo object from JPA objects dynamically using reflection. One of the matching criteria is, that the field names should match.
I was successfully able to implement this for two pojo objects. But when I tried using JPA objects as one of the object parameter, it didn't work. Based on my research I found out that the method Class.getDeclaredFields() , does not give me the name of the field but the getter/setter method name of member variable for JPA objects.
Can anyone please give me a lead or direction as in where/what should I look to accomplish this task?
JPA providers will often use dynamic proxy classes of your concrete JPA classes, so you have no guarantee of the field names in the proxy. The only guarantee about a proxy is that the methods are the same. Use a debugger to inspect the runtime class of the JPA class instances that you're trying to use and you'll see the problem.
The best you'll be able to do is use reflection to call methods on JPA-returned objects.
All that aside, I don't really see why you'd need to POJO-ify an entity class anyway, since an entity is primarily an annotated... POJO.
One of the matching criteria is, that the field names should match.
I think that this is the root of your problem. There is simply no guarantee that a Java object's field names will match the names of getters and setters ... or anything else. If you make this assumption, you will run into cases where is doesn't work.
The best solution is to simply not use this approach. Make it a requirement that the Pojo classes conform to the JavaBeans spec and rely on the setters to set the properties. This is likely to work more often than making assumptions about (private) field names.
In fact, the state of a generic JPA object implemented using a dynamic proxies could well be held in a hash map. Those fields you can see could simply be constants used for something else.
My question more specificity is this:
I want users on multiple front ends to see the "Type" of a database row. Let's say for ease that I have a person table and the types can be Student, Teacher, Parent etc.
The specific program would be java with hibernate, however I doubt that's important for the question, but let's say my data is modelled in to Entity beans and a Person "type" field is an enum that contains my 3 options, ideally I want my Person object to have a getType() method that my front end can use to display the type, and also I need a way for my front end to know the potential types.
With the enum method I have this functionality but what I don't have is the ability to easily add new types without re-compiling.
So next thought is that I put my types in to a config file and simply story them in the database as strings. my getType() method works, but now my front end has to load a config file to get the potential types AND now there's nothing to keep them in sync, I could remove a type from my config file and the type in the database would point to nothing. I don't like this either.
Final thought is that I create a PersonTypes database table, this table has a number for type_id and a string defining the type. This is OK, and if the foreign key is set up I can't delete types that I'm using, my front end will need to get sight of potential types, I guess the best way is to provide a service that will use the hibernate layer to do this.
The problem with this method is that my types are all in English in the database, and I want my application to support multiple languages (eventually) so I need some sort of properties file to store the labels for the types. so do I have a PersonType table the purely contains integers and then a properties file that describes the label per integer? That seems backwards?
Is there a common design pattern to achieve this kind of behaviour? Or can anyone suggest a good way to do this?
Regards,
Glen x
I would go with the last approach that you have described. Having the type information in separate table should be good enought and it will let you use all the benefits of SQL for managing additional constraints (types will be probably Unique and foreign keys checks will assure you that you won't introduce any misbehaviour while you delete some records).
When each type will have i18n value defined in property files, then you are safe. If the type is removed - this value will not be used. If you want, you can change properties files as runtime.
The last approach I can think of would be to store i18n strings along with type information in PersonType. This is acceptable for small amount of languages, altough might be concidered an antipattern. But it would allow you having such method:
public String getName(PersonType type, Locale loc) {
if (loc.equals(Locale.EN)) {
return type.getEnglishName();
} else if (loc.equals(Locale.DE)){
return type.getGermanName();
} else {
return type.getDefaultName();
}
}
Internationalizing dynamic values is always difficult. Your last method for storing the types is the right one.
If you want to be able to i18n them, you can use resource bundles as properties files in your app. This forces you to modify the properties files and redeploy and restart the app each time a new type is added. You can also fall back to the English string stored in database if the type is not found in the resource bundle.
Or you can implement a custom ResourceBundle class that fetches its keys and values from the database directly, and have an additional PersonTypeI18n table which contains the translations for all the locales you want to support.
You can use following practices:
Use singleton design pattern
Use cashing framework such as EhCashe for cashe type of person and reload when need.
I have some POJOs that are used to shuffle data around in my application and its webservices. We have just introduced an annotation to help us verify that String fields in those POJOs are of a certain length. This lets us validate the POJOs instead of waiting for the database layer to puke out an exception when it persists.
I would now like to do an analysis on those objects that will tell me what fields are Strings that do not have this new annotation. I want to do this so that I can get a list of fields that do not have this annotation so that it can be compared to its corresponding DB field and have the annotation added with the right length as its parameter.
No we cannot get a better correlation between our POJOs and our database objects.
No our database objects don't have this validation available. We really want this validation to happen on the POJOs as it is simpler to validate and report on invalid data at runtime.
Is there some static analysis tool that would help me with this task?
Sure.
Parse the Java code. Walk the AST. Find the fields of interest (may require that you also do name and type resolution ("symbol tables") so you can tell your fields from arbitary other fields) in the ASTs for your classes, and inspect the AST for the desired annotation.
You can do this with any Java AST parser (and name resolver). I think Eclipse can provide this. Our DMS Software Reengineering Toolkit can do this. ANTLR appears to have a Java parser, but I doubt if it has Java name and type resolution.
I opted to use annotations for the runtime validation needs and then crafted a unit test to verify that all fields were annotated. This was inspired by #c0mrade .
So the annotation is #Length and requires an integer parameter. At runtime the validator iterates over fields and looks for the #Length annotation and makes sure its applied on a String field. It then looks at the length of the Strings value and makes sure it is less than or equal to the parameter for the annotation.
In a unit test I load all of the classes for my POJOs by package. I then iterate over those classes, iterate over each classes fields, and finally check and see if the field is a String and has the #Length annotation assigned. If the field is a String and does not have #Length, it adds the class and field name to a list of Strings. The assertion for the test is that this list is empty.
What is the best way to convert types in a Struts2 application?
Right now I want to create a CRUD for a certain hibernate entity in my application. Say I wanted to change the Account that a User is associated with. I can just pass in the parameter user.account.id with a specific value, provided that I have all of the proper getters/setters.
This works perfectly fine when creating an object for the first time, where the account would be null. This makes ognl create a new account object, and set the id to what was passed in.
The problem happens when trying to change the encapsulated Account object. Using the same user.account.id parameter, ognl interprets this as getUser().getAccount().setId(param). Hibernate interprets this as an attempt to change the primary key.
I understand why it does this, I am just wondering if there is better way for handling this case. This is very common in our application, and I don't want to have to keep creating multiple objects and marshaling them over before I save them via hibernate.
Does anyone no a better way to solve this problem in struts2?
Type Converters for Persistence
Create a type converter for the entity and then just pass user.account, rather than user.account.id. This will invoke getUser().setAccount(account) and wont cause you the headaches.
When you update the record, just pass user.account as a hidden field in the form.
As for a widespread solution for your entities, you have a few options:
Multiple Converters
Create an abstract type converter that handles most of the logic so that you have a subclass-per-entity that is really lightweight. Register each converter in your xwork-conversion.properties.
Interface-Driven Converter
The approach that I use is that I have an interface called IdBasedJpaEntity which 99.9% of my entities implement. It defines a getId() method of type Integer. I then have a JpaDAORegistry singleton class that I create when my app starts. I register each of my entities with it and it constructs a single instance of each DAO (basically, a de-facto singleton). I have a map of entity class to DAO instance. This allows my type converter to look up the appropriate DAO instance for any given IdBasedJpaEntity, allowing me to have a single JpaEntityConverter class that works with any entity that implements the interface. This route is a little bit more work up front, but has proven highly reusable for me.