In a Jersey class, Which is more appropriate of the two:
On an instance variable
#PathParam("service-id")
private String serviceId;
On a method argument
public Response subscribe(#PathParam("service-id") String serviceId){}
I'm using first one only because service-id is required by almost all my methods. However, a colleague of mine had a comment over this approach that ultimately Jersey classes are based on servlets and servlets should not have stateful variables.
I read about this in the JSR-311 java docs
Because injection occurs at object creation time, use of this
annotation on resource class fields and bean properties is only
supported for the default per-request resource class lifecycle.
Resource classes using other lifecycles should only use this
annotation on resource method parameters.
Since in a webapp, my Jersey class is going to follow per-request resource class lifecycle, I feel first approach is safe. Thoughts please :)
It is made safe by virtue of only allowing this annotation in request-scope (so that every request gets its own bean/resource instance and there is no shared state).
I'd probably give each method the full set of parameters, though, even if it is a bit repetitive. Makes it easier to see at a glance what is going on. That's a code style issue, though, and people can have different opinions here.
This is only coding styles issues since this code has exactly the same result.
I also prefer to define it in the method, instead of defining it in the instance.
Whatever, once compiled, the result is the same! :)
Related
What I have known are:
annotation was added in java 5
annotation can be using in method, class, and property
annotation can work in RUNTIME, CLASS, SOURCE( I don't know how to work with CLASS and SOURCE, and their's features)
annotation with retention which is RUNTIME can be implement when java program is running.
And I want to implement a annotation to have follows features:
ensure class only being allowed to create a instance
ensure methods only being allowed to access method in the class
it is like as friend in c++
it is same as public and private , but more dynamicall, like
#MyAnnotation(allowMethods={xxx.doSomething})
public void getValue(){}
the getValues method only can be accessed in the instance self and xxx.doSomething() method
What should I do and learn in next?
And Where can I learn about these?
I think you might be misunderstanding something there. Annotations are descriptive elements, not parts of your program. You can write as many annotations as you want, and people who use your code will still be able to ignore them.
That said, an annotation that enforces a policy (as yours does) can actually be implemented, either at compile or at runtime, but you need an external mechanism to help you. I can think of 3:
Annotation processing lets you interact with the compiler and process annotations by generating code or by omitting compiler errors. Unfortunately, I don't think it will work for your case, as you want to protect your annotated type from instantiation, and that means the call site doesn't actually have an annotation. Annotation processing only gives you access to the actual code pieces that have annotations, not to those that refer to them.
AspectJ allows you to write policy enforcement aspects and omit compiler errors, based on static pointcuts. The problem here is that static pointcuts have very limited semantics, so while you could forbid the instantiation of your class altogether, or from certain packages, you could not limit the your class instantiations to 1.
The third way, and probably the only sane way is that you use a container like Spring or Guice and configure your class as singleton. As long as you only retrieve your class from the container, it will never create a second instance.
Finally: If you want to limit the number of instantiations of your class, you can always use a classic Singleton pattern approach.
My questions are about the lifecycle of controllers in the Play framework for Java, if the controllers are stateful instances or stateless with static methods, and how to use dependency injection in the controller code.
Is each web request handled by a new instance of a Play controller class, i.e. can a controller store state in fields such as services injected into the controller constructor?
(where in the documentation is it explained?)
Has the Play framework changed since earlier versions (and if so, at what version?) regarding if controllers are stateful instances or stateless controllers with static methods?
Where can you see code examples about how the framework injects services into a controller instance when stateful controller is used and example of how to inject services into a static controller method?
Regarding the latter, i.e. injection into a static method I suppose that would either have to be a parameter to the method which the frameworks will add, or if not possible you maybe instead will have to use a service locator from within the method e.g. instantiate a Guice module class and then use "injector.getInstance" from within the static controller method.
This subject is touched in the section "Dependency injecting controllers" at the following page:
https://www.playframework.com/documentation/2.4.x/JavaDependencyInjection
However, it does not show with code how to actually inject services into a controller instance (but probably the same way as other "components" i.e. with #Inject annotation) and certainly it does not currently show how to use DI with a static controller method.
I am confused about these things because I have not found documentation being clear about my questions, and I have also read in a Play book (from 2013) that the controller methods should be programmed as stateless and the controller methods should be static.
However, when now using activator for generating a Play application for Java with the latest Play version (2.4.6) I can see that the generated Controller method (Application.index) is NOT static.
Also, at the following documentation page, the controller method is NOT static:
https://www.playframework.com/documentation/2.4.x/JavaActions
This is confusing, and since it is VERY fundamental to understand whether or not each request is handled by a Controller instance or not (i.e. if state can be used) I think this should be better documented at the page about Controller/Actions than the current documentation (the above linked page) which is not explaining it.
The documentation about dependency injection touches the subject about static and non-static methods at the section "Dependency injecting controllers" mentioning "static routes generator" but I think it should be better explained including code examples.
If someone in the Play team is reading this question, then please add some information to the above linked pages, for example please do mention (if my understanding is correct) that in previous versions of Play the controller methods were static and for those versions you should never store state in fields, but in later versions (beginning from version x?) each request is handled by an instance of a controller and can therefore use state (e.g. constructor parameters injected by the framework).
Please also provide code examples about injection used with static controller methods and injection into stateful controller instances with one instance per request.
The section "Component lifecycle" in the dependency injection page only mentions "components" but I think it should also be explicit about the controller lifecycle and its injection, since it is such a fundamental and important knowledge to communicate clearly to all developers to avoid bugs caused by misunderstandings about being stateful or not.
Is each web request handled by a new instance of a Play controller class, i.e. can a controller store state in fields such as services injected into the controller constructor? (where in the documentation is it explained?)
As far as I can tell, controllers are by default singleton objects. This is not clearly documented, but it is implied that controller instances are reused. See the migration guide for Playframework 2.4:
The injected routes generator also supports the # operator on routes, but it has a slightly different meaning (since everything is injected), if you prefix a controller with #, instead of that controller being directly injected, a JSR 330 Provider for that controller will be injected. This can be used, for example, to eliminate circular dependency issues, or if you want a new action instantiated per request.
Also, check this commend made by James Roper (Play core committer) about if controllers are singleton or not:
Not really - if using Guice, each time the controller is injected into something, a new instance will be created by default. That said, the router is a singleton, and so by association, the controllers it invokes are singleton. But if you inject a controller somewhere else, it will be instantiated newly for that component.
This suggests that the default is to reuse controller instances when responding to requests and, if you want a new action per request, you need to use the syntax described in the migration guide. But... since I'm more inclined to prove and try things instead of just believe, I've created a simple controller to check that statement:
package controllers
import play.api._
import play.api.mvc._
class Application extends Controller {
def index = Action {
println(this)
Ok(views.html.index("Your new application is ready."))
}
}
Doing multiple requests to this action prints the same object identity for all the requests made. But, if I use the # operator on my routes, I start to get different identities for each request. So, yes, controllers are (kind of) singletons by default.
Has the Play framework changed since earlier versions (and if so, at what version?) regarding if controllers are stateful instances or stateless controllers with static methods?
By default, Play had always advocated stateless controllers, as you can see at the project homepage:
Play is based on a lightweight, stateless, web-friendly architecture.
That had not changed. So, you should not use controllers' fields/properties to keep data that changes over time/requests. Instead, just use controllers' fields/properties to keep a reference to other components/services that are also stateless.
Where can you see code examples about how the framework injects services into a controller instance when stateful controller is used and example of how to inject services into a static controller method?
Regarding code examples, Lightbend templates repository is the place to go. Here are some examples that use dependency injection at the controllers level:
https://github.com/adrianhurt/play-api-rest-seed
https://github.com/knoldus/playing-reactive-mongo
https://github.com/KyleU/boilerplay
Dependency Injection with static methods is not supported, and that is why Playframework stills offers old apis to use with static methods. The rule of thumb here is: choose between DI and static methods. Trying to use both will just bring complexity to your application.
Ok, thank you marcospereira.
I have now also confirmed that you indeed get different instances (different toString values which can be printed/logged in a controller method) of the controller for each request.
For those who are interested, the solution (to get different instances of controller class for each request) is to use for example the following:
GET / #controllers.Application.index()
instead of the following:
GET / controllers.Application.index()
in the file "conf/routes"
AND to also use the following:
routesGenerator := InjectedRoutesGenerator
instead of the following:
routesGenerator := StaticRoutesGenerator
in the file "build.sbt"
Regarding the statement that Play has a "stateless" architecture:
Maybe I am wrong, but as far as I understand the terminology, the "stateless" means that the web server does not store any state between requests?
The word "stateless" does not mean that a controller instance can not use fields, e.g. injected into the constructor.
If an injected object is stored as a field in a controller, then that field is a "state" of the controller.
Therefore, even if you use "InjectedRoutesGenerator" and the "#" prefix to get "stateful" controller instances, that injected "state" is only stored within one request, so you can still say that the framework itself is "stateless" since the server does not store any state between multiple requests.
Please do correct me if I have misunderstood something about Play being stateless.
Is it possible to load the value for the #PATH annotation from configuration (web.xml, etc) for a given class?
#Path(<value loaded from config>)
public class myRestService {
...
Independent of JAX-RS: Annotations in Java are compile time constants so they can't be changed at runtime.
I don't know your use case but possible ways to change the values of the annotations are:
Replacing variables before compilation, e.g. through a maven plugin.
Adding the #Path annotations dynamically like described here.
Using one generic ResourceClass mapped to /* which decides which subresource should be returned.
No comment if one of these approaches makes sense as I don't know why you want to change them. As the URI names a resource I don't see any reason to change it. See also: Cool URIs don't change
Update: JAX_RS_SPEC-60 requests "A Dynamic way to register JAX-RS resources (not based on annotations)".
According to JAX-RS specification (here), there is no standard way to do this, I think.
I've written a state machine for navigating an automated telephone system, where each state is represented by its own Java class file, for a total of 50+ classes. Rather than write the instantiation and factory code myself, I decided to use Spring for bean definition and dependency injection. This works fine, however I have lost compile-time type checking by moving from:
State next = getState(Instructions.class);
to
ApplicationContext ctx = ...
State next = ctx.getBean("instructions", State.class);
Instead of having compiler checks that I've specified a real, existing state, I now have to rely on the id being spelled properly in both my source code and the bean xml.
Is there a better way to do this? I haven't worked extensively with Spring since early 2.0 days, so I don't have much real world experience to draw on. What are the drawbacks and advantages of this approach? Is there is something extra I could to to verify proper id strings are used?
Consider using Spring autowiring and in your class have:
class StateMachine
{
#Autowired
State next;
}
You can also use qualifiers to select amongst the different implementation you may have of State.
Turn off lazy initialization of Spring, and you'll at least cure the type safety department. You could also consider a 'grand central station' bean into which all of the states are inserted by name, this resulting in a yell if any go missing. You can still mispell in your Java code.
I would personally go about it one of two ways:
1) If only a few states needed access to a few other states, I would inject those directly (like Steve said in his answer):
#Inject
public setInstructions(Instructions instructions) { ... }
2) On the other hand, if any state needs access to any other one, no one wants to inject the other 49 states into each of the 50 classes, so I would have one central class that had all 50 injected and basically build my state machine in that class.
Spring really is a factory when it comes down to it, but tying yourself to the Spring API kind of goes against their philosophy, and as you mentioned, you lose type safety.
Our Topic object has BOTH isChannel and getChannel public methods. The object graph is too complex to change this. Channel has an Integer type.
We are migrating from one application server to Tomcat. When using this expression ${topic.channel.type}, in JSPs our current app server finds the getChannel method. However, Tomcat finds the isChannel method and we get errors since the return type is a Boolean, not a Channel. Is there a way to tell Tomcat to prefer getters over boolean public methods?
For now I'm just going to write a helper function or expose a new method, but I have a feeling I'm going to come across this quite a bit during the migration.
Unfortunately, you can't force a method call like that.
I have checked the Javabeans and EL specifications, but nowhere is specified what the preferred method is when both isXXX() and getXXX() methods are present. However, I do agree that it makes more sense to prefer the getXXX() one in this particular case. This should also be programmatically possible. I think it's worth the effort to report this as an issue against the Tomcat EL implementation.
In theory, this should be more of a JavaBeans issue than an EL implementation issue. One thing you might try is to find out how the java.beans.Introspector views your Topic class. One way to do that would be to run this code I wrote a while back for the Struts wiki. Depending on the complexity of your class, it might make sense to create an explicit java.beans.BeanInfo class to force the channel property to always be exposed as an Integer.