Inject #Context fields using Guice's #Inject (into subresources) - java

I am currently developing a REST webservice using Jersey and Guice as a DI-container.
For handling the requests I am relying on a GuiceServletContextListener which is configured similar to the following:
bind(UserResource.class);
//Some other root-level resources for REST
serve("/rest/*").with(GuiceContainer.class);
As I have to deal with hierarchical data (One user should have their own items and it should be possible to access items of other users in the form of /rest/user/[Username]/item). For this, I am using Jersey's support for subresources.
For example, my UserResource contains the following method (ItemResource.Factory is a factory interface whose implementation is automatically provided by Guice's FactoryModuleBuilder):
#Inject
private ItemResource.Factory _itemResourceFactory;
#Path("/{username}/item")
public ItemResource getItems(#PathParam("username") String username) {
User user = //...
return this._itemResourceFactory.create(user);
}
ItemResource (the subresource) then again is implemented as a normal Jersey class based on the User passed in in the constructor.
However, my subresources need access to #Context fields (like UriInfo or HttpServletRequest), too. According to the Jersey documentation, #Context fields are not injected for subresources as their lifecycle is unknown (and the documentation seems to be true).
This is very unfortuante for me: I really need access to those values.
As a workaround, I am currently passing those values as additional constructor parameters to my subresources which I perceive as everything but comfortable.
Is there any possibility to tell Jersey to inject them anyway?
Nevertheless, even better would be if Guice itself was able to inject the #Context fields.
Simply swapping the #Context for #Inject, however, doesn't work as Guice has no registrations for types like UriInfo or HttpServletRequest.
Can I somehow create those mappings?
The problem is, that I don't know how to access the request specific values inside a Guice Provider implementation.
Are there maybe any helper methods to get access to the current instances of those Jersey objects so I can write the necessary providers?
Or are those implementations maybe already available somewhere out there?

I am not sure I understood your problem. Can you post the code related to "passing those values as additional constructor parameters"?
You can inject the Context like this:
#Path("/{username}/item")
public ItemResource getItems(#Context HttpServletRequest request, #PathParam("username") String username) {

Maybe you could inject fields programmatically? Guice provides this through the Injector class:
Injector injector = Guice.createInjector(...);
injector.injectMembers(someObjectToInject);
See http://code.google.com/p/google-guice/wiki/Injections for more information on this topic.

Related

Is there a way to provide an attribute to all models in Spring?

Thymeleaf dropped template expressions like #session, #httpServletRequest etc. in Version 3.1 (https://www.thymeleaf.org/doc/articles/thymeleaf31whatsnew.html).
We used those a lot in relatively large applications. I wrote an interceptor to populate those attributes at every request since I don't want to add them in every Controller needed (like described in the migration guide).
Does anybody know a better way of achieving this?
This is already the best method to populate attributes at each request, compared to the earlier methods defined in the Spring framework documentations.
I learned that #ControllerAdvice can be used in this case (see https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc).
Classes annotated with #ControllerAdvice, can have methods annotated with #ModelAttribute to populate attributes over multiple Controllers (all of them if not specified otherwise).
In my case:
#ControllerAdvice
public class CommonDataAdvice {
#Autowired
private HttpServletRequest request;
#ModelAttribute("request")
public HttpServletRequest populateRequest(){
return request;
}
}

Difference between javax.security.enterprise.SecurityContext and javax.ws.rs.core.SecurityContext?

I am struggling to understand when and how to use the different interfaces.
They seem to be quite similar, with some minor differences in method names to dynamically check security roles or retrieve the Principal, but - as far as I am currently understanding - are only accessible in their specific context.
I am trying to implement fine grained authorization with specific requirements.
Mainly the roles are not stored in the tokens, but must be read from a table in the database.
Therefore I have an implementation of IdentityStore that provides a CallerPrincipal with all available roles.
The IdentityStore is used by my HttpAuthenticationMechanism implementation, which is fairly simple, thus all it does is for valid requests to call HttpMessageContext.notifyContainerAboutLogin to push the CallerPrincipal into the SecurityContext - as far as I know.
Because there are a lot of generic endpoints in the codebase with path parameters, that decide which role has to be checked I need a generic way of checking if the user is in a role depending on the value of some path segments of the requested uri.
I created a method interceptor for that, where I want to access the SecurityContext, but both interfaces have their problems here:
#Interceptor
public class RolesAllowedInterceptor {
#Context
private UriInfo uriInfo;
// this injection is always null
#Context
private javax.security.enterprise.SecurityContext securityContext;
// this injection works
#Context
private javax.ws.rs.core.SecurityContext securityContext;
#AroundInvoke
public Object validate(InvocationContext ctx) throws Exception {
... // read path param to retrieve role and check SecurityContext.isUserInRole()
}
}
The injection of javax.security.enterprise.SecurityContext does not work. I assume the reason for this is, that the interceptor is called in a JAX-RS context.
The injection of javax.ws.rs.core.SecurityContext works (my assumption in 1. is based on this). But when SecurityContext.isUserInRole(String) is called, the debugger shows, that the Principal does not have any of the groups (roles in my business context) that were assigned via my IdentityStore implementation and thus the validation incorrectly fails.
I am currently using another approach with ContainerRequestFilter to set the javax.ws.rs.core.SecurityContext explicitly, which is working fine for the interceptor, but not with the javax.annotation.security.RolesAllowed annotation. For that I shifted the invocation of my IdentityStore into the filter, because I obviously do not want to call it twice.
I am not looking for complete code examples/solutions.
I am merely trying to understand why there are different interfaces of SecurityContext, as the Java Docs do not elaborate on that.
And therefore hopefully understand how I can use RolesAllowed for static endpoints and my interceptor for generic endpoints, without the need of a ContainerRequestFilter to set the SecurityContext for the later.
--
For context: I am using Payara Micro and jakartaee-api:8.0.0

Java: How do I unit test where there are encapsulated injected or generated dependencies?

SUMMARY:
I have a self-contained class for performing a proxied login and then filling a HttpServletResponse object with authentication content a browser can use. When testing my code, how can I provide mocked services into a class that has no setters?
DETAILS:
I've severely edited my proxied login code into this snippet.
It asks the server for a login form.
It sends back the credentials.
It gets the server's approval and passes it to the browser
(response).
The trimmed code looks like this:
private static final Log log = LogFactory.getLog(MyClass.class);
#Inject()
private UserService userService;
public void performProxyLogin(HttpServletResponse response,
UserDTO userDTO, String url) {
String username = getUsername(userDTO);
String password = getPasswordFromUserService(username);
// MyRequest only has data, organizing a Http Request.
MyRequest myRequest = prepareInitialGetRequest(url);
// processURLRequest() encapsulates use of HttpURLConnection.
// MyResponse only has data, organizing a Http Response.
MyResponse myResponse = processURLRequest(myRequest);
myRequest = prepareLoginRequest(myResponse, username, password);
myResponse = processURLRequest(myRequest);
// Transfer data into the response, and from there into the browser.
fillResponseWithProxiedResult(response, myResponse)
}
To make this work I think I need to inject a mocked Log or LogFactory, a mocked UserService, and a way of getting a mocked HttpURLConnection.
However, all of the advice I've seen involves code with setters, which the test suite can use to plug in mocked objects.
How do I provide my class its needed mocked objects?
Bite the bullet and provide a package-private setter for this field.
If you want to use mocks, there's no value in letting the injection framework set up a mock which you can inject, since you're adding more ceremony and overhead to the set-up of your test.
If you want to validate that you have a service injecting correctly, you wouldn't want to use mocks at all (think "integration test" with real or pseudo-real components).
Many of the other answers hint at it, but I'm going to more explicitly say that yes, naive implementations of dependency injection can break encapsulation.
The key to avoiding this is that calling code should not directly instantiate the dependencies (if it doesn't care about them). This can be done in a number of ways.
The simplest is simply have a default constructor that does the injecting with default values. As long as calling code is only using the default constructor you can change the dependencies behind the scenes without affecting calling code.
This can start to get out of hand if your dependencies themselves have dependencies and so forth. At that point the Factory pattern could come into place (or you can use it from the get-go so that calling code is already using the factory). If you introduce the factory and don't want to break existing users of your code, you could always just call into the factory from your default constructor.
Beyond that there's using Inversion of Control. I haven't used IoC enough to speak too much about it, but there's plenty of questions here on it as well as articles online that explain it much better than I could.
If it should be truly encapsulated to where calling code cannot know about the dependencies then there's the option of either making the injecting (either the constructor with the dependency parameters or the setters) internal if the language supports it, or making them private and have your unit tests use something like Reflection if your language supports it. If you language supports neither then I suppose a possibility might be to have the class that calling code is instantiating a dummy class that just encapsulates the class the does the real work (I believe this is the Facade pattern, but I never remember the names correctly)]

How to retrieve matched resources of a request in a ContainerRequestFilter

I am working on a WebService using JAX-RS/Jersey.
I've set up a ContainerRequestFilter whose purpose is to authenticate the user. I only need to protect some of the paths with authentication, the rest can be available to everyone.
I want to retrieve matchedResources / matchedResults via ExtendedUriInfo in my ContainerRequestFilter so that I can check if the path should be protected or not. Is there a way to create a filter which is invoked after ExtendedUriInfo is populated, but before the matched resource class and method is invoked?
Here is a more general answer (for instance if you're using another jax-rs implementation like CXF):
Just add the following in your filter class as an instance variable:
#Context
ResourceInfo info;
"javax.ws.rs.container.ResourceInfo is a new JAX-RS context which can
be injected into filters and interceptors and checked which resource
class and method are about to be invoked."
(source : https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Basics#JAX-RSBasics-ResourceInfo)
Original answer here
Found a way to do it with ContainerRequestFilter:
public void filter(ContainerRequestContext requestContext) {
UriRoutingContext routingContext = (UriRoutingContext) requestContext.getUriInfo();
ResourceMethodInvoker invoker = (ResourceMethodInvoker) routingContext.getInflector();
Class<?> className = invoker.getResourceClass();
Method methodName = invoker.getResourceMethod();
}
I managed to figure it out.
The approach I have found to work is to abandon doing this in the ContainerRequestFilter and create a ResourceFilterFactory instead. In the ResourceFilterFactory I can use
AbstractMethod.isAnnotationPresent(clazz)
to determine if my custom annotation is present. If my annotation is present, I can then return a list containing my AuthenticationContainerRequestFilter.
Another tip for anyone reading this answer is that injection in the ContainerRequestFilter will not work when using the ResourceFilterFactory approach. What I did was to do any injection in the ResourceFilterFactory and then pass the injected objects to the ContainerRequestFilter via its constructor.

Using Aspect Oriented Programming for user authentification in Java?

I like to add an user authentification to my REST webservice (Guice + Jersey).
I first wanted to solve the authentification with the Google Guice method interceptions. For example:
#Path("user")
public class User {
#OnlyAdmin
#Post
public void addUser(String apiKey) {
}
}
But unfortunately Guice only support AOP for classes with a no-argument constructors.
Is it generally a good idea to use AOP for user authentification?
Are there other frameworks to build an user authentification?
Edit: Framework is maybe the wrong term. I'm only looking for a way to inject some code in every annotated method and this code should check the parameters of the method
The only important point for AOP to work in your case is that your classes get created by Guice.
If you have constructors with arguments, ensure that they are injectable (directly or with assisted injection).
It wouldn't be AOP but you could inject a current user role bound to the request scope wherever the user needed to be checked and use either method intercepts or explicit logic to check that the right user class is performing some action.

Categories

Resources