JSF managed property injection null inside REST resource - java

I have a REST resource class (so the one listening for incoming REST connections from the web) which needs to access a managed bean library controller.
Upon invocation however I get a null pointer exception.
#ApplicationPath("webresources")
#Path("/record")
#Stateless
public class RecordResource
{
#ManagedProperty(value = "#{libraryController}") // this references the #ManagedBean named libraryController
private LibraryController libraryController;
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadWeb(InputStream inputStream)
{
//Null exception below !
getLibraryController().function();
}
public LibraryController getLibraryController()
{
return libraryController;
}
public void setLibraryController(LibraryController libraryController)
{
this.libraryController = libraryController;
}
}
The getters/setters are ok so I don't know why the proper constructor for LibraryController is not called.

The injection fails because the client class is not a #ManagedBean, therefore the container has no notion of the JSF context inside RecordResource.
See this question for further clarification.
As a workaround, consider to use an #EJB controller and inject it by means of #EJB annotation. Otherwise please explain what's the business logic behind this design.

Related

How to propagate same instance using CDI

I have a web application with JAX-RS, CDI and EJB. In each resource I inject a Stateless SessionBean, and my question is whether it is possible to inject the same instances into a provider of JAX-RS and the Stateless SesionBean. I am trying to pass some data that come in each request to the Stateless SesionBean from a ContainerRequestFilter. All EJB components are accessed only by jax rs resources.
Example:
public class Bean {
private String attr;
// getter and setter
}
#Stateless
public class BeanService {
#Inject
Bean bean;
public void doStuff() {
bean.getAttr();
// do something with bean.attr
}
}
#Path("/bean")
public class BeanResource {
#Inject
BeanService service;
#GET
public void doStuff() {
service.doStuff():
}
}
#Provider
public class BeanRequestFilter implements ContainerRequestFilter {
#Inject
Bean bean;
#Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
String data = null; // <- get data from request
bean.setAttr(data);
}
}
Update
Change the Bean for Pojo, my only intention is use a class that hold some state that come in every request and can be transmited in each invocation, since the PojoResource to PojoService. I want to do it in this way because all the services retrive this data and I don't want to pass this as parameter on every method.
This looks like your Bean class is essentially request scoped, so changing it to:
#RequestScoped
public class Bean {
...
}
should have the desired effect. The same instance will be injected in both the BeanRequestFilter and the BeanService.
However, I think you may also get what you're looking for by injecting the ContainerRequestContext directly into the BeanService and forgetting about Bean altogether.
#Stateless
public class BeanService {
#Context
ContainerRequestContext containerRequestContext;
public void doStuff() {
// <- get data from request
}
}
If you want the Bean to be a kind of singleton using CDI see the #ApplicationScoped annotation (in that case Bean should be Sersializable)
Or if you want the EJB BeanService to be a singleton see the #Singleton annotation
Before answering the question, Bean should never be updated. A concept of bean is that which provides a service, and uses data to process a request.
That said, you can of course provide data as bean, but then the data needs to be produced at one point to be used, and not to be updated.
I would therefore use the BeanRequestFilter to produce the bean, and let the BeanService inject the produced bean.
This notwithstanding however, i see that this is a request based data? is it a header data?, request parameter? Then i would suggest that you use the jax-rs #QueryParam or #HeaderParam or #PathParam or #FormParam or #CookieParam within the jax-rs resource class, and then provide the data as a domain object parameter to your BeanService thus:
#Path("/api/resource-path")
public class MyResource {
public void processSomething(#QueryParam("qparam") String param, #HeaderParam("hparam") String hParam) {
MyDomain domain = new MyDomain(qParam, hParam);
myService.process(domain);
}
}

Jersey - Inject variable from filter as RequestScoped

I want to perform authentication in a filter before my resource method is called. Within this filter I would also like to retrieve the permissions of a user and pass it on through a RequestScoped #Inject annotation.
#Authenticated
public class AuthenticationFilter implements ContainerRequestFilter {
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
public #interface Authenticated {};
#Inject
private ISecurityHandler handler;
public AuthenticationFilter() {}
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Filter out unauthorized
// Retrieve user permissions
this.handler.setUserPermissions(...);
}
}
Resource:
#Path("my-path")
public class GetVisitorsDataResource {
#Inject private ISecurityHandler handler;
#GET
#Path("resource-method")
#Authenticated
#Produces(MediaType.APPLICATION_JSON)
public Response resource() {
System.out.println(handler.getUserPermissions());
return Response.ok().build();
}
}
I have registered the filter and a Factory for the injection.
public static class SecurityHandlerProvider implements Factory<ISecurityHandler> {
#Override
public ISecurityHandler provide() {
System.out.println("PROVIDING SECURITY CONTEXT!");
return new SecurityHandlerImpl();
}
#Override
public void dispose(ISecurityHandler instance) {
System.out.println("DISPOSING SECURITY CONTEXT!");
}
}
I have also bound it.
bindFactory(SecurityHandlerProvider.class).to(ISecurityHandler.class).in(RequestScoped.class);
It is important that the object is created when a request is received and only accessible within that request. When the request is finished, the dispose method should be called. The only way I can achieve something similar is through the #Singleton annotation. However, the object is not destroyed after the request is completed and is shared across all requests.
I have been investing too much time into this issue already, is there perhaps anybody that knows how to achieve the preferred result?
Your code doesn't really make much sense. One place you are injecting ISecurityHandler, and another place SecurityHandler, but the factory is for ISecurityContext. I will just assume those are typos or copy and paste errors.
Aside from that I'll assume that really all is ok, since you you said it works as a singleton. So I'm guessing you are facing the "Not inside a request scope" error. The easiest fix for that is to just inject using javax.inject.Provider, which allows us to lazily retrieve the object. When the object is retrieve, it will be withing a request scope.
#Inject
private javax.inject.Provider<ISecurityContext> securityContextProvider;
#Override
public void filter(ContainerRequestContext context) throws IOException {
ISecurityContext sc = securityContextProvider.get();
}
...
bindFactory(SecurityHandlerProvider.class)
.to(ISecurityContext.class)
.in(RequestScoped.class);
NB, you should also make sure to annotate you AuthenticationFilter with #Priority(Priorities.AUTHENTICATION) so that it occurs before any other filter even you my prefer it to be a #PreMatching filter. The earlier into the system the authentication happens, the better, I'd say.
As an aside, you may want to look into Jersey's RolesAllowedDynamicFeature. It allows you to use the jsr250 annotations #RolesAllowed, #DenyAll, and #PermitAll for your resource classes and methods.
It is basically a filter that occurs after your Priorites.AUTHENTICATION filter, and it looks up the javax.ws.rs.core.SecurityContext from the ContainerRequestContext to look up roles. You just need to create the SecurityContext inside your authentication filter, so the next filter can look it up.
You can see an example here. You can check the user permission in the isUserInRole. When the set the SecurityContext, Jersey's filter will be called afterwards, and it calls your isUserInRole. Doing it this way, you get access control for free.

Singleton implementation of a Spring bean

We have a Spring bean implemented as a singleton (default). This bean is used as part of an web-service, and at times when multiple simultaneous requests are triggered, the responseholder (singleton bean) throws a NullPointerException when trying to retrieve. This usually happens when the response is build, and then a new request is triggered before sending the original response back.
Can this be due to the Singletion implementation of the bean? If yes, is there wouldn't changing to prototype solve my problem. What about initiating it with the new operator always? Will there be any performance impacts on doing so? Or is there a better way.
Any help would be greatly appreciated.
Edit:
Code details
public class BuildToolRequestProcessor {
private BuildToolResponse buildToolResponse;
.....
//And it has been referenced in the code in different methods, setting the response details..
public String process(BuildToolRequestXml buildToolRequestXml) throws Exception {
buildToolResponse.setLocation(location);
...
public String handleDetails(BuildToolRequestXml buildToolRequestXml) throws Exception {
buildToolResponse.setSchedule(schedule);
...
// And in another method, when I try to retrieve the Location, it throws a Null Pointer Exception..
buildToolResponse.getLocation().getPinCode()
//Bean configuration
<bean id="buildToolResponse"
class="com.raj.buildTool.processor.BuildToolResponse"/>
Additional Notes: I tried introducing a delay before bulding the response of the first request, shooting another request. The second request resets the Location to NULL, and hence NPE is thrown while trying to retrieve the Location. Could this be because of the singleton? Also I haven't used initialized the buildToolResponse again with the new operator, but the class BuildToolResponse extends from BuildToolResponseBuilder, which I am initializing using 'new' to build the response.
Can this be due to the Singletion implementation of the bean? If yes, is there wouldn't changing to prototype solve my problem.
If you have a singleton bean, make sure that this bean does not maintain any state. This means, it should not have any field that is reinitialized based on some methods, except for the injection of another beans or resources that is done by Spring. This may cause concurrency issues, specially when the bean is used in several threads (in this case, to attend multiple requests done to your web service).
This is an example of a bad design for a Spring bean that will be used on multiple threads:
#Component
public class SingletonByDefaultBean {
private StringBuilder responseBuilder;
#Autowired
private FooService fooService;
public String methodUsedInSeveralThreads() {
//here you will have a concurrency issue
responseBuilder = new StringBuilder();
//write contents into the response
//...
//return the response
return responseBuilder.toString();
}
}
To solve this, you have two approaches:
Remove any state of the bean and move the attributes into method local variables:
#Component
public class SingletonByDefaultBean {
//private StringBuilder responseBuilder;
#Autowired
private FooService fooService;
public String methodUsedInSeveralThreads() {
StringBuilder responseBuilder = new StringBuilder();
//write contents into the response
//...
//return the response
return responseBuilder.toString();
}
}
Change the scope of the bean to prototype
#Component
#Scope("prototype")
public class SingletonByDefaultBean {
private StringBuilder responseBuilder;
#Autowired
private FooService fooService;
public String methodUsedInSeveralThreads() {
responseBuilder = new StringBuilder();
//write contents into the response
//...
//return the response
return responseBuilder.toString();
}
}
What about initiating it with the new operator always?
Refer to this answer to know how you can create instances your classes manually and make them been managed by Spring. It is not that easy and I would recommend using these approaches only if you really understand what you're doing.

Injecting principal into resource method in RESTEasy with Guice

I am developing a REST API using RESTEasy with Guice and at the moment I am trying to incorporate basic authentication by use of an annotation similar to the #Auth found in Dropwizard. With
#Path("hello")
public class HelloResource {
#GET
#Produces("application/json")
public String hello(#Auth final Principal principal) {
return principal.getUsername();
}
}
the hello resource invocation should be intercepted by some code performing basic authentication using the credentials passed in the Authorization HTTP request header and on success injecting the principal into the method principal parameter. I would also like to be able to pass a list of allowed roles to the annotation, e.g. #Auth("admin").
I really need some advice in what direction to go to achieve this?
I think your best bet would be using an intermediate value within request scope. Assuming that you didn't put HelloResource in singleton scope, you can inject this intermediate value in some ContainerRequestFilter implementation and in your resource, and you can fill it inside this ContainerRequestFilter implementation with all authentication and authorization info you need.
It will look something like this:
// Authentication filter contains code which performs authentication
// and possibly authorization based on the request
#Provider
public class AuthFilter implements ContainerRequestFilter {
private final AuthInfo authInfo;
#Inject
AuthFilter(AuthInfo authInfo) {
this.authInfo = authInfo;
}
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// You can check request contents here and even abort the request completely
// Fill authInfo with the data you need
Principal principal = ...; // Ask some other service possibly
authInfo.setPrincipal(principal);
}
}
#Path("hello")
public class HelloResource {
private final AuthInfo authInfo;
#Inject
HelloResource(AuthInfo authInfo) {
this.authInfo = authInfo;
}
#GET
#Produces("application/json")
public String hello() {
// authInfo here will be pre-filled with the principal, assuming
// you didn't abort the request in the filter
return authInfo.getPrincipal().getUsername();
}
}
public class MainModule extends AbstractModule {
#Override
protected void configure() {
bind(AuthFilter.class);
bind(HelloResource.class);
bind(AuthInfo.class).in(RequestScoped.class);
}
}
And even if you did put the resource (or even the filter) in singleton scope for some reason, you can always inject Provider<AuthInfo> instead of AuthInfo.
Update
It seems that I was somewhat wrong in that the filter is by default not in singleton scope. In fact it seem to behave like singleton even though it is not bound as such. It is created upon JAX-RS container startup. Hence you will need to inject Provider<AuthInfo> into the filter. In fact, the container startup will fail if AuthInfo is injected into the filter directly while being bound to request scope. Resource (if not explicitly bound as singleton) will be OK with direct injection though.
I have uploaded working program to github.

Invoke controller method from java class

I just want to know whether controller class method is accessible from another java class.
following is my controller and its method.
#Controller
public class TestResultUploadController {
#RequestMapping(method = RequestMethod.POST,value="/uploadTestResult")
public #ResponseBody
String uploadTestResult(String testResultBarcode,int deviceLoc) {
//some code goes here
return something;
}
I just want to call this controller method from another java class.
How can I make it work?
please suggest..
Short answer: yes, it is possible. In your other class/thread, you can do
// this will create a new instance of that controller where no fields are wired/injected
TestResultUploadController controller = new TestResultUploadController();
controller.uploadTestResult("someString", 1234);
However, keep in mind that your setup is highly unusual and all your autowired fields wouldn't be wired correctly. If you obtain your controller from the context, you'd be able to have your fields wired/injected properly:
// obtain controller bean from context, should have fields wired properly
TestResultUploadController controller = ctx.getBean(TestResultUploadController.class);
controller.uploadTestResult("someString", 1234);
or you can, in your other class, have:
#Autowired private TestResultUploadController controller;
....
public void doStuff(){
controller.uploadTestResult("someString", 1234);
}
Again, this is highly unusual, but highly possible. However, just cause something is possible to be done, doesn't mean you should do it. I would recommend the more common Spring/MVC approach in which you outsource the business logic to Services. Basically, to have something like this:
#Controller
public class TestResultUploadController {
#Autowired private UploadTestResultService uploadTestResultService;
#RequestMapping(method = RequestMethod.POST,value="/uploadTestResult")
public #ResponseBody String uploadTestResult(String testResultBarcode,int deviceLoc) {
return uploadTestResultService.uploadTestResult(testResultBarcode, deviceLoc);
}
}
And in your thread:
//somehow get the service
UploadTestResultService uploadTestResultService = //somehowGetTheService (whether from context or in some other way)
uploadTestResultService.uploadTestResult(testResultBarcode, deviceLoc);
That way, you'd be able to mock the UploadTestResultService in your tests of the controller, and you'd also be able to test the uploadTestResult method of that service on its own without it being in a controller.
EDIT:
How to obtain the Spring context is outside of the scope of this question. I assume you know basic Spring and also basic java.

Categories

Resources