In the following document, detailing a study from 2009 regarding annotation validations, the following is stated:
http://www.ii.uib.no/~federico/latex/annotationlimitations2.pdf
Let us point out that in practice it can be possible to annotate
directly a field of an object as they do in [3]:
#IntRange(min=1,max=100000)
private int Amount;
However we decided not to offer this possibility for a simple reason:
if the field is private, the framework must first change its
visibility to public by means of reflection, before to be able to
retrieve its value. We consider a very bad practice to allow an
external framework to tamper with the visibility of object properties.
So instead of putting the annotation on the private variable declaration as in the above example, they put the annotation on the public getter() method instead.
public class WebForm {
private int Amount;
...
#IntRange(min=1,max=100000)
public int getAmount {
return this.Amount;
}
}
This paper is dated 2009, so I'm wondering does this still apply? If I am using the Hibernate Validator, following JSR-380 & the Bean Validation 2.0 specification, do I need to declare validation annotations at the getter level to avoid the private variable being made public by reflection by the Hibernate framework?
Most/All of the examples I see online do not do this - they are happy to put the annotation above the private variable declaration.
Using reflection to change the visibility of a field doesn't actually change the visibility of that field. It returns a copy of the field that is public. No this does still not apply.
This paper never applied to Hibernate Validator and Bean Validation. We support annotations on private fields and we use reflection to access the content of the field.
Indeed we do that by making the field accessible to our code. This does not change the visibility of the field itself though.
Related
I am trying to add a simple controller method, but I am running into the following
Exercise.java:[13,1] variable id might not have been initialized
Here is the code that I am working with
#RequestMapping(value = "/exercises/{id}")
public ResponseEntity<Optional<Exercise>> getExerciseById(Model model, #PathVariable Integer id) {
Optional<Exercise> exercise = exerciseRepository.findById(id);
if(id!=null)
return new ResponseEntity<Optional<Exercise>>(exercise, HttpStatus.OK);
else
return new ResponseEntity<Optional<Exercise>>(exercise, HttpStatus.NOT_FOUND);
}
I am using an Optional<Exercise> here because I am taking advantage of the build in method findById from the JpaRepository package. I haven't found any good posts on how to handle this is. This is probably something simple. I've found some documentation around this:https://www.java67.com/2016/07/how-to-fix-variable-might-not-have-been-initialized-error-in-java.html, but I could use a little help understanding the best way to fix this. This is the exercise classe
#Entity
#Table(name = "exercise")
#Value
#NoArgsConstructor
public class Exercise {
#Id
#NonNull
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private int chapterId;
private String exercise;
private String answer;
private String question;
private String a;
private String b;
private String c;
}
tldr;
I don't think JPA plays well with the immutable entity created by #Value. Use #Data instead.
ihnbtdttrt (i have nothing better to do than to read this);
This partially guesswork, but since it has seemed to help, this is what I think is happening:
When you call findById(), JPA creates a new entity object using a no-argument constructor, and then sets the fields individually afterwards. (I'm not sure if it uses setters or sets the fields directly using reflection).
The #Value annotation, as documented here, makes a class immutable, with all the fields private and final and with no "setters" created. This means that the only way to set the fields is by passing the field values into a constructor with appropriate arguments. After that the fields are not changeable.
Since JPA initializes entities using the no-args constructor and tries to set the fields afterwards, with your setup, it uses the no-args constructor and ends up with an entity object where none of the fields have been initialized but none of them are modifiable after the constructor. All private, final fields, with no setters. Then it tries to call entity.getId(), and the id field hasn't been initialized, leading to the above error.
To fix this, you can use the #Data annotation instead of #Value. This is similar, but doesn't create an immutable object. In particular, it generates "setter" functions and the fields are not set to final. This is the type of Java bean that JPA expects, one that can be initialized with a no-argument constructor and then have the fields set afterwards.
There may be ways to configure JPA to create objects differently, so that it passes all the data into a constructor so that you can have immutable entities. I know that some Spring DI stuff is configurable to initialize using rich constructors like this, but Idk about JPA.
For what it's worth, I appreciate the value of immutable objects for clean code, but it's not uncommon to find the above pattern of no-arg construction + post-construction setting when using the popular Java frameworks like JPA/Hibernate, Spring, etc. They don't always play well with immutability.
While reading the Oracle documentation on annotations (quite new to this concept), I came across the following snippet in the beginning (link at the bottom). I am not clear on what the example is illustrating. Is the public #interface definition an enhanced version of a normal interface definition? id(), engineer() etc are methods that return default values if not specified in the interface implementation? But then the instantiation is confusing, is it providing an implementation of an interface where id() returns 2868724 etc? Also not clear what the function travelThroughTime() is for. Any clarifications appreciated:
/**
* Describes the Request-For-Enhancement(RFE) that led
* to the presence of the annotated API element.
*/
public #interface RequestForEnhancement {
int id();
String synopsis();
String engineer() default "[unassigned]";
String date(); default "[unimplemented]";
}
#RequestForEnhancement(
id = 2868724,
synopsis = "Enable time-travel",
engineer = "Mr. Peabody",
date = "4/1/3007"
)
public static void travelThroughTime(Date destination) { ... }
http://docs.oracle.com/javase/1.5.0/docs/guide/language/annotations.html
To break down your questions:
Is #interface just an enhancement of interface?:
No, #interface is declaring something quite different from a standard interface- you are essentially declaring an annotation type. Making this declaration enables the declared thing to be used as an annotation in other code. So the declaration:
public #interface RequestForEnhancement
enables the annotation #RequestForEnhancement to be used in later code.
An annotation describes metadata for a method or a class. The #RequestForEnhancement annotation, for example, might be placed in front of a method in another class to indicate that some developer wants that method to be changed in some way.
Declaring an interface, by contrast, is declaring the signature of a group of functions. Classes which later implement an interface must then provide implementations of those functions.
What are the "methods" (synopsis(), engineer(), etc.) in the annotation body for? These are not really methods like you would be used to seeing in a class or interface definition. Instead, these represent fields that the annotation you've just declared has. A #RequestForEnhancement annotation on a method should indicate what the requested change to the method is, and possibly who is expected to implement the enhancement to the method. Thus the fields synopsis and engineer are fields that can be included in the annotation.
What does this section mean?:
#RequestForEnhancement(
id = 2868724,
synopsis = "Enable time-travel",
engineer = "Mr. Peabody",
date = "4/1/3007"
)
public static void travelThroughTime(Date destination) { ... }
This is an example of using the annotation that we've declared in the block starting with #RequestForEnhancement. Usages like this will likely occur all over your codebase, in many different classes, once the annotation has been defined. In this particular example, there is a method travelThroughTime(Date destination) in some class which apparently doesn't work very well. Some developer coming across the method thought it should be improved by making it do what it appears to claim to do (travel through time). That developer decided to reflect his request by putting an #RequestForEnhancement annotation on the method with some information about when the request was made, who was expected to make the enhancement, etc.
Sure, but how do you use the contents of an annotation for anything useful? (A question I'll ask for you :-) )
So let's say I want to write a tool which looks through all of my code for methods annotated with #RequestForEnhancement and send an e-mail to the engineers listed in the request, along with information about the annotation and the request for enhancement. How would I get started?
The basic mechanism to find out what methods have an annotation and the way to get values from the annotation is through Java reflection. A tutorial which includes an example of annotations and reflection is here (it's actually a good tutorial on annotations in general).
So sure, you can use reflection to get info out of these annotations, but when would you run a tool to use the info from the annotations? (another one I'll ask for you) Java provides the ability for you to define annotation processors which use annotation information when your code is compiled. Here's what looks like a reasonable tutorial. You can also use the information in your annotations at runtime. If you've ever used JavaFX, for example, you may have noticed that annotations can affect runtime behavior (adding #FXML to a field helps JavaFX fill that field with a value defined in your fxml).
Assuming a JPA entity with (for example) an long id generated automatically:
#Entity
#AutoProperty
public class SomeItem {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long Id;
...
}
Is there any reason to not generate setter and getters for this Id? One might be tempted to not generate a setter for example, since it is the responsibility of JPA to generate the ID.
I see that other comments has misguided you so I feel myself obliged to elaborate on this issue a bit, even though I can't give you a scientific and complete answer. #vcetinick wrote the current accepted answer:
You may find that you may be able to get away [..] from the persistence side of things.
This quote in particular is wrong. All depends on where you put your #Id annotation. The specification says:
If the entity has field-based access, the persistence provider runtime
accesses instance variables directly.
Thus you are not required in any way to provide a setter or getter. Because you annotated your field and not a getter method (annotating the setter method will be ignored and have no bearing).
However, if you write a getter method, and annotated this method with your #Id annotation instead of your field, then we would tell our persistence provider to access our field through the accessor (getter) and mutator (setter) methods and not use reflection. In that case, both a getter and a setter should be present. The book Pro JPA 2: Mastering the Java™ Persistence API writes on page 71 (bold markup by me!):
When property access mode is used, the same contract as for JavaBeans applies, and there must be getter and setter methods for the persistent properties. The type of property is determined by the return type of the getter method and must be the same as the type of the single parameter passed into the setter method. Both methods must be either public or protected visibility.
Therefore, I usually annotate my id field, and write both a setter and getter method, but the setter method I give protected access. I just don't want any other pieces of code to have easy write access to such an important field. I don't know if this would cause problems in other domains. I'm no expert. But I don't find any rationale either as to why not setup an id attribute in this way. See also the Netbeans forums.
You may find that you may be able to get away without putting a getter/setter on the JPA Entity from the persistence side of things. But if you start dealing with entities that are serialized from other sources, even from your view in some cases, you will need a way to set the ID of the entity to let JPA know that it is dealing with an existing entity, if you cant set the id, then the persistence layer will just treat it as a new Object.
Id is your primary key without it you will never able to insert records in the database.
In your case #GeneratedValue(strategy=GenerationType.AUTO) it ensures that id will be generated for each persist but then also you will need a method to access it since it is primary identification of entity you should provide access to it .
Its like you asking some person his name and he doesn't provide it to you and you would thing he is just being rude .
I want to force future users of a class to access a private member also from future code written in that class only through an accessor method (even through junit or anything like that).
is there a way to do it in java? can someone show an example if possible?
You cannot force to do that, but you can create a method and document that enforcement in the javadoc.
private int myMember;
/**
* ATTENTION: use this method instead of setting the member directly.
*/
public void setMyMember(int value) {
this.myMember = value;
}
Also, there is an alternative solution which might work. Use ThreadLocal, like this:
private final ThreadLocal<String> member = new ThreadLocal<String>();
public void setMember(final String value) {
member.set(value);
}
The member field is final and cannot be changed. Therefore, clients will be forced to call the setter directly.
As long as the field is part of the class, anyone can access it directly. This can be a problem when we try to force all (co-)authors to go through the getters/setters because those method do some conversion, checking or bookkeeping stuff. Like incrementing internal counters.
A general solution, that comes to mind: it could be possible by using annotations. You'd have to create an annotation (and the annotation processor code) to ensure, that it is a compile time error if the field is used outside of it's getter/setter method:
#GetterSetterAccessOnly
private int value;
If you want to prevent reflection you can use a SecurityManager. If this is not an option you can get the call stack with Thread.currentThread().getStackTrace() and check the caller is from your class.
Two problems with this are; the performance won't be great. Anything you can do in the method you can do externally so the simplest work around is to copy its contents without the check. ;)
I suggest you document your reason for not allowing access this way.
Make use of inheritance to hide the field:
Do your class with all the fields and getter/setters that you need. (You may make it abstract)
Do a child class, that inherits from the previews one, and since the field isn't accessible, you force the use of the getter/setter pair.
As you are talking about the accessing in the same class, they have all the freedom to access the private member directly as well as through accessor method if that member has. So basically you cannot prevent them using the member directly in the same class.
I am afraid there is no standard way to do that. If a user has access to a class instance, although a private member is declared private, permissions can be changed at runtime and accessed anyway.
You need a classloader that enforces permissions. You can make an OSGi Bundle and enforce a control policy over the instance of your objects exported as services through interfaces. However this will tie you to an OSGi container to run your application.
Well, if they have access to your code, they can do anything they want. In the worst case, they remove your getters and setters and just put in a public field instead ;)
But of course you can motivate them to not access the variable directly with an according design:
you should check whether the others should rather implement subclasses instead of changing the class itself. Then private fields are, of course, only accessed via setters and getters.
you could move the data into a different class, and use your getters and setters to access the data in the other class. Doing this just for the sake of not having the data directly in your class is maybe a bit counter-intuitive, but since you probably have a good reason why they shouldn't access that very data, it indicates a different responsibility. So refactoring to meet the SRP is a good idea anyways.
I've started reading the Enterprise Java Beans 3.0 book by Bill Burke and Richard Monson-Haefel and in chapter 4 it has this code
#PersistenceContext(unitName="titan") private EntityManager manager;
The class then has methods that access this field (which is never set in the constructor and has no setter method). So how does the container set this private field with an actual instance? I'm assuming there's some reflection and/or bytecode magic going on - how is that done?
getDeclaredFields() will return a list of fields declared in the class.
Container loops through all the fields checking for appropriate annotations. Once the needed field is found, it invokes setAccessible(true) on that field in order to be able to manipulate it from the code where it normally would not have been accessible.
manager.getClass().getDeclaredFields()
Will get you access to the fields. See the javadocs here