Is it somehow possible to annotate a Java Method in that way that i later can give another Method a Field Identifier or something like that, so that this Method can call the right one?
I know that normally you would do this with interfaces, but in my case this would be a immense count of interfaces... I need to use this in Entity Classes for my Database (and i'm not allowed to use a ORM Mapper)
For example: I have the Entity
public class Account{
private String username;
private String password;
private String name;
private String mail;
public void setUserName(String username){
this.username = username;
}
public String getUserName(){
return username;
}
[all other getter/Setter...]
}
Now i want to tell a Method that it need to validate a Field, for example the username field.
The Method that does should look like this:
public void validateField(XXX Field, Entity entity) throws ValidationFailedException, EmptyFieldException;
where XXX is somehow the FieldIdentifier.
Is that in any way possible in Java?
My only guess it that i Use public static final ìnt stuff in there to give every field a Method or so...
What do you use? I don't see any annotations from which I can guess your framework. If you use Hibernate, you can use something like #NotNull or something else, or even do your custom validation:
This is how you would go with your example:
public class Account{
#NotNull(message="This field should not be null")
private String username;
#NotBlank(message="This string should not be empty or null")
private String password;
private String name;
private String mail;
public void setUserName(String username){
this.username = username;
}
public String getUserName(){
return username;
}
[all other getter/Setter...]
}
http://silentwalker.wordpress.com/2009/04/07/custom-validation-in-hibernate/
You can also create your own annotations without using any framework and use them #prepersist or whatever. Basically the sky is the limit.
P.S Since you don't want to use any non internal code, here is how you can approach:
First, you can define an annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface NotNull{
public String message() default "";
}
Then, before persisting the class, you would inspect its fields:
So, you have something like this:
Field[] classFields = yourObjectPrePersist.getClass().getDeclaredFields();
for (int i = 0; i < classFields.length; i++) {
classFields[i].setAccessible(true);//take notice that if you use a SecurityManager, you should work around it
if (classFields[i].getAnnotation(NotNull.class) != null) {
Object value = classFields[i].get(yourObjectPrePersist);
//here check if value is null or not and then return the message
if (value == null) {
throw new SomeException(((NotNull) classFields[i].getAnnotation(NotNull.class)).message());
}
}
}
Annotations don't seem like the right solution to the problem you describe.
One possibility would be to pass in the name of the field that needs to be validated, then used the java.beans.BeanInfo class to access the field values of the Entity. This will allow you to access arbitrary attributes of an object without having to deal with all of the complexity of reflection.
You can use reflection for this; see the documentation for java.lang.reflect.Field. The caller can pass in the field-name as a string, and validateField can use something like Field f = entity.getClass().getField(fieldName).
But this is not usually a great idea . . . reflection is awesome, but it requires a lot of boilerplate code, and you pay a high price in maintainability. (You also pay a performance penalty, though in my experience the maintainability penalty is much worse than the performance penalty.) Personally I use reflection a lot in test code (it can help in writing extremely comprehensive tests), and I make use of frameworks like Spring and Hibernate that depend on reflection, but I avoid it in my own production code.
You could use a generic interface
public interface Field {
public String getValue();
}
and call your validate method with anonymouse classes
validator.validate(new Field() {
return account.getUsername()
});
(or with old java)
validator.validate(new Field() {
public String getValue() {
return account.getUsername();
}
});
Otherwise what about using java.lang.Methode directly?
P.S.: Sorry for the quote, stackoverflow did not let me post my text directly, said it was not formatted correctly :-/
Related
Sorry if the title is a bit confusing, I didn't really know how to word what I wanted to ask.
Basically, I am making an api call to a database that returns data as such:
[{"profiles":{"testexample":{"addresses":[{"city":"","street1":"","street2":"apt 320"}],"addressType":"HOME","city":"","dateOfBirth":"","emailAddress1":"","emailAddress2":"","emailAddresses":[{"email":"","preferred":1,"type":"BUSINESS"},{"email":"","preferred":0,"type":"PERSONAL"}],"firstName":"","lastName":"","phoneNumber":"","phoneNumbers":[],"phoneType":"HOME","postalCode":"","preferred":1,"street1":"","street2":""}]
The code I have below works fine when the database returns a non-empty profiles {}. I have the following Java classes that looks like the following:
public class Account {
#JsonProperty("profiles")
private Profiles profiles;
#JsonProperty("profiles")
public Profiles getProfiles() {
return profiles;
}
#JsonProperty("testexample")
public void setProfiles(Profiles profiles) {
this.profiles = profiles;
}
}
public class Profiles {
#JsonProperty("testexample")
private Profile testExample;
#JsonProperty("testexample")
public Profile getTestExample() {
return testExample;
}
#JsonProperty("testexample")
public void setTestExample(Profile testExample) {
this.testExample = testExample;
}
}
public class Profile {
#JsonProperty("dateOfBirth")
private String dateOfBirth;
#JsonProperty("dateOfBirth")
public String getDateOfBirth() {
return dateOfBirth;
}
#JsonProperty("dateOfBirth")
public void setDateOfBirth(String dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
}
So what I want to do when I get the data is check whether the getProfiles() returns empty, so I don't make the calls to anything within that object.
Please note, for the sake of simplicity I omitted other parts of the classes to focus primarily on what I wanted
This is what I have so far, and it works when the profiles {} is not empty
Account response = access.lookup(id, type); //This is to grab the response from the database, which is working.
response.getProfiles(); //This is the part that works when it has a profiles {} not empty, but fails on empty.
So what happens is that I don't get an error for response.getProfiles(), but if I tried to do response.getProfiles().getDateOfBirth(), it won't work because it will give a null pointer exception since the dateOfBirth isn't there.
I want to avoid calling anything within response.getProfiles() by skipping it if it's empty.
You need some basic null checking. The most basic way is to assign a new variable and check.
Profiles profiles = account.getProfiles();
if(profiles != null) {
//dosomething with profiles.getDateOfBirth()
}
The more "modern" functional Java way would be to use the Optional class.
String dateOfBirth = Optional.ofNullable(account.getProfiles())
.map(profile -> profile.getDateOfBirth)
.orElse(null);
(A note about your example: In the Account class, you have this.
#JsonProperty("testexample")
public void setProfiles(Profiles profiles) {
this.profiles = profiles;
}
Which appears to be an incorrect #JsonProperty annotation and might be causing some problems.
That said, it is not necessary to annotate the getters and setters. The one annotation on the field is sufficient.)
Serialization is a lot of boilerplate. I was wondering if I could use annotations to write that for me, thus allowing the structure of the object to double as its on-disk format.
I know Jackson exists but ObjectMapper feels too magical and I'd like to just have something like this:
#SynthSerializer
public class Foo {
public final String name;
public final String description;
public Foo(String name, String description) {
this.name = name;
this.description = description;
}
}
//Following code generated at compile time by #SynthSerializer:
public class FooSerializer: implements Serializable {
//Boilerplate, you know the drill
}
Incidentally, from what I understand modifying source code using annotations is a hack, but creating altogether new classes (like in my example) is an intended use case for annotations. That's true, yes?
Anyway, is this kind of generation possible with annotations? Is this a sane way to do something like this? And do annotation processors that already do something like this exist?
I am considering moving from Hibernate to jOOQ but I can't find e.g.
how to have Pattern-Constraints on a String like this in Hibernate:
#NotEmpty(message = "Firstname cannot be empty")
#Pattern(regexp = "^[a-zA-Z0-9_]*$", message = "First Name can only contain characters.")
private String firstname;
How would I do that in jOOQ?
The "jOOQ way"
The "jOOQ way" to do such validation would be to create either:
A CHECK constraint in the database.
A trigger in the database.
A domain in the database.
After all, if you want to ensure data integrity, the database is where such constraints and integrity checks belong (possibly in addition to functionally equivalent client-side validation). Imagine a batch job, a Perl script, or even a JDBC statement that bypasses JSR-303 validation. You'll find yourself with corrupt data in no time.
If you do want to implement client-side validation, you can still use JSR-303 on your DTOs, which interact with your UI, for instance. But you will have to perform validation before passing the data to jOOQ for storage (as artbristol explained).
Using a Converter
You could, however, use your own custom type by declaring a Converter on individual columns and by registering such Converter with the source code generator.
Essentially, a Converter is:
public interface Converter<T, U> extends Serializable {
U from(T databaseObject);
T to(U userObject);
Class<T> fromType();
Class<U> toType();
}
In your case, you could implement your annotations as such:
public class NotEmptyAlphaNumericValidator implements Converter<String, String> {
// Validation
public String to(String userObject) {
assertNotEmpty(userObject);
assertMatches(userObject, "^[a-zA-Z0-9_]*$");
return userObject;
}
// Boilerplate
public String from(String databaseObject) { return databaseObject; }
public Class<String> fromType() { return String.class; }
public Class<String> toType() { return String.class; }
}
Note that this is more of a workaround, as Converter hasn't been designed for this use-case, even if it can perfectly implement it.
Using formal client-side validation
There's also a pending feature request #4543 to add more support for client-side validation. As of jOOQ 3.7, this is not yet implemented.
I recommend you don't try to use jOOQ in a 'hibernate/JPA' way. Leave the jOOQ generated classes as they are and map to your own domain classes manually, which you are free to annotate however you like. You can then call a JSR validator before you attempt to persist them.
For example, jOOQ might generate the following class
public class BookRecord extends UpdatableRecordImpl<BookRecord> {
private String firstname;
public void setId(Integer value) { /* ... */ }
public Integer getId() { /* ... */ }
}
You can create your own domain object
public class Book {
#NotEmpty(message = "Firstname cannot be empty")
#Pattern(regexp = "^[a-zA-Z0-9_]*$", message = "First Name can only contain characters.")
private String firstname;
public void setId(Integer value) { /* ... */ }
public Integer getId() { /* ... */ }
}
and map by hand once you've retrieved a BookRecord, in your DAO layer
Book book = new Book();
book.setId(bookRecord.getId());
book.setFirstname(bookRecord.getFirstname());
This seems quite tedious (and ORM tries to spare you this tedium) but actually it scales quite well to complicated domain objects, in my opinion, and it's always easy to figure out the flow of data in your application.
I worked out a concept to conditionally validate using JSR 303 groups. "Conditionally" means that I have some fields which are only relevant if another field has a specific value.
Example: There is an option to select whether to register as a person or as a company. When selecting company, the user has to fill a field containing the name of the company.
Now I thought I use groups for that:
class RegisterForm
{
public interface BasicCheck {}
public interface UserCheck {}
public interface CompanyCheck {}
#NotNull(groups = BasicCheck.class)
private Boolean isCompany
#NotNull(groups = UserCheck.class)
private String firstName;
#NotNull(groups = UserCheck.class)
private String lastName;
#NotNull(groups = CompanyCheck.class)
private String companyName;
// getters / setters ...
}
In my controller, I validate step by step depending on the respective selection:
#Autowired
SmartValidator validator;
public void onRequest(#ModelAttribute("registerForm") RegisterForm registerForm, BindingResult result)
{
validator.validate(registerForm, result, RegisterForm.BasicCheck.class);
if (result.hasErrors()
return;
// basic check successful => we can process fields which are covered by this check
if (registerForm.getIsCompany())
{
validator.validate(registerForm, result, RegisterForm.CompanyCheck.class)
}
else
{
validator.validate(registerForm, result, RegisterForm.UserCheck.class);
}
if (!result.hasErrors())
{
// process registration
}
}
I only want to validate what must be validated. If the user selects "company" fills a field with invalid content and then switches back to "user", the invalid company related content must be ignored by the validator. A solution would be to clear those fields using Javascript, but I also want my forms to work with javascript disabled. This is why I totally like the approach shown above.
But Spring breaks this idea due to data binding. Before validation starts, Spring binds the data to registerForm. It adds error to result if, for instance, types are incompatible (expected int-value, but user filled the form with letters). This is a problem as these errors are shown in the JSP-view by <form:errors /> tags
Now I found a way to prevent Spring from adding those errors to the binding result by implementing a custom BindingErrorProcessor. If a field contains null I know that there was a validation error. In my concept null is not allowed - every field gets annotated with #NotNull plus the respective validation group.
As I am new to Spring and JSR-303 I wonder, whether I am totally on the wrong path. The fact that I have to implement a couple of things on my own makes me uncertain. Is this a clean solution? Is there a better solution for the same problem, as I think this is a common problem?
EDIT
Please see my answer here if you are interested in my solution in detail: https://stackoverflow.com/a/30500985/395879
You are correct that Spring MVC is a bit picky in this regard,and it is a common problem. But there are work-arounds:
Make all your backing fields strings, and do number/date etc conversions and null checks manually.
Use JavaScript to set fields to null when they become irrelevant.
Use JavaScript to validate fields when they are entered. This will fix almost all of your problems.
Good luck!
I know this question is old, but I came upon it looking for an answer for a different situation.
I think for your situation you could use inheritance for the forms and then use two controller methods:
The forms would look like this:
public class RegistrationForm
{
// Common fields go here.
}
public class UserRegistrationForm
extends RegistrationForm
{
#NotNull
private String firstName;
#NotNull
private String lastName;
// getters / setters ...
}
public class CompanyRegistrationForm
extends RegistrationForm
{
#NotNull
private String companyName;
// getters / setters ...
}
The controller methods would look like this:
#RequestMapping(method = RequestMethod.POST, params = "isCompany=false")
public void onRequest(
#ModelAttribute("registerForm") #Valid UserRegistrationForm form,
BindingResult result)
{
if (!result.hasErrors())
{
// process registration
}
}
#RequestMapping(method = RequestMethod.POST, params = "isCompany=true")
public void onRequest(
#ModelAttribute("registerForm") #Valid CompanyRegistrationForm form,
BindingResult result)
{
if (!result.hasErrors())
{
// process registration
}
}
Notice that the #RequestMapping annotations include a params attribute so the value of the isCompany parameter determines which method is called.
Also notice that the #Valid annotation is place on the form parameter.
Finally, no groups are needed in this case.
In playframework, it uses javassist library to let the public fields of a class can be used as property.
See the example:
public class User {
public String name;
}
User user = new User();
user.name = "Freewind"
System.out.println(user.name);
In compilation time, play enhanced the bytecode with javassist, the final code is similar to:
public class User {
private String name;
public String getName() { return this.name; };
public void setName() { this.name = name; };
}
User user = new User();
user.setName("Freewind");
System.out.println(user.getName());
You can see not only the field name has getter and setter, but also the invocations of it changed to getters and setters.
I wonder if there is any other way to do the same (use other things than javassist)?
I found Annotation Processing Tool, but I'm not sure it can do it.
Or aspectj? Or something else?
You can look at Project Lombok, which does something similar, but with annotations. With project lombok you do need to use the getters and setters in your own code.
Not without other tools.
Unlike C#, Java does not support properties.