I have a resource class and I'd like to be able to check an authentication token before the resource method is called, thus avoiding having to pass the token directly into the Resource method.
I have added the following to web.xml:
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>com.michael.services.interceptors.AuthorisationInterceptorImpl</param-value>
</context-param>
My interceptor is implemented as follows:
#Provider
public class AuthorisationInterceptorImpl implements javax.ws.rs.container.ContainerRequestFilter {
#Inject
private ApiAuthenticationService apiAuthenticationService
#Override
public void filter(ContainerRequestContext requestContext) {
//Code to verify token
}
}
The filter method is being called before the methods in my resource class; however, the apiAuthenticationService is not being injected and is null when I attempt to call its methods.
I'm using Tapestry 5.3.7, Tapestry-Resteasy 0.3.2 and Resteasy 2.3.4.Final.
Can this be done ?
I don't think this will work, based on a quick glance at the tapestry-resteasy code.
The #Inject annotation is part of tapestry-ioc; if a class is not instantiated by Tapestry, the #Inject annotation is not honored.
Filters defined in web.xml are instantiated by the servlet container (Jetty, Tomcat, etc.) which do not have any special knowledge of Tapestry and Tapestry annotations.
I think you will be better off contributing a filter into Tapestry's HttpServletRequestHandler or RequestHandler pipelines (see their JavaDoc). I'm not sure how you can gain access to the ContainerRequestContext, however.
With tapestry-resteasy you don't need to define the provider in the web.xml file.
If you want to use Tapestry's autobuild mechanism just move your provider to the .rest package together with your resources.
If don't want to use autodiscovery/autobuild just contribute it to javax.ws.rs.core.Application
#Contribute(javax.ws.rs.core.Application.class)
public static void configureRestProviders(Configuration<Object> singletons, AuthorisationInterceptor authorisationInterceptor)
{
singletons.add(authorisationInterceptor);
}
Even though you can use rest providers for security is probably a good idea to take Howard's advice and implement your own filter in the tapestry pipeline.
BTW, you can also give tapestry-security a try :)
Related
I have a Quarkus application using current versions of Vaadin Flow and Quarkus (23.2.4 and 2.13.1.Final). I want to have a VaadinServiceInitListener to check access annotations on the views (#RolesAllowed(...)) using AccessAnnotationChecker. I believe annotating the implementation with #VaadinServiceEnabled
should fix this, but I need to register it in META-INF/services/com.vaadin.flow.server.VaadinServiceInitListener to have it activated. This is how to do it when not using a dependency injection framework. Then everything works as expected and I can use AccessAnnotationChecker to see if the user has access to that view, on BeforeEnterEvent.
I also notice the message Can't find any #VaadinServiceScoped bean implementing 'I18NProvider'. Cannot use CDI beans for I18N, falling back to the default behavior. on startup. Strangely, implementing I18NProvided in a class and annotating it with #VaadinServiceEnabled and #VaadinServiceScoped makes that message go away, eg. it is recognized by CDI.
Why isn't my VaadinServiceInitListener implementation recogized? Currently it is annotated with
#VaadinServiceEnabled
#VaadinServiceScoped
#Unremovable
My pom.xml include
vaadin-quarkus-extension,
quarkus-oidc,
quarkus-keycloak-authorization,
vaadin-jandex
Instead of using a listener, you can use a CDI event.
Quarkus's dependency injection solution is based on CDI, so you can use the same events. Here's an example
public class BootstrapCustomizer {
private void onServiceInit(#Observes
ServiceInitEvent serviceInitEvent) {
serviceInitEvent.addIndexHtmlRequestListener(
this::modifyBootstrapPage);
}
private void modifyBootstrapPage(
IndexHtmlResponse response) {
response.getDocument().body().append(
"<p>By CDI add-on</p>");
}
}
More information here https://vaadin.com/docs/latest/integrations/cdi/events
I am using JBoss 7.1 and Java 1.6.
I would like to integrate a Guice service with by JAX-WS endpoint. Using the interceptor pattern described by Gunnar.Morling I am able to properly instantiate the Guice modules when using a stateless bean as a webservice. However i am not able to do the same with a simple POJO annotated webservice. Is this possible has anyone found a workaround. Below is a summary of my efforts so far.
#UsesGuice #Interceptor
public class GuiceInterceptor {
#Inject
private GuiceInjectorHolderBean injectorHolder;
#AroundInvoke
public Object aroundAdvice(final InvocationContext ctx) throws Exception {
if (ctx.getTarget().getClass().isAnnotationPresent(UsesGuice.class)) {
final Injector injector = injectorHolder.getInjector();
injector.injectMembers(ctx.getTarget());
}
return ctx.proceed();
}
}
The GuiceInjectorHolderBean is the a sinlgeton bean responsible for triggering the guice wiring. The annotation class required follows
#Retention(RUNTIME)
#Target(TYPE)
#InterceptorBinding
public #interface UsesGuice {}
the JAX-WS POJO class
#UsesGuice
#WebService(serviceName = "EchoServiceService", portName = "EchoServicePort", ame = "EchoServiceImpl", targetNamespace = "lala")
public class EchoServiceImpl implements EchoService
{
#Inject
MyGuiceInjection injection;
#Override
#WebMethod
public String sayHello(final String msg)
{
return "Hello " + injection.call(msg);
}
}
Thanks in advance
Dimitri
Your Current Approach
In your code, javax.interceptor annotations #Interceptor, #InterceptorBinding and #AroundInvoke are supported by CDI and EJB standards and not by Guice. Guice uses proprietary AOP interception via org.aopalliance.intercept.MethodInterceptor interface and calling the method AbstractModule.bindInterceptor.
So you're trying to bootstrap Guice injection on your endpoint by:
using a non-Guice interceptor on the endpoint's method
within the #AroundInvoke method, programmatically invoking the Guice Injector, with injection target being the intercepted endpoint
That begs the Q, what to use for 1?
'Bootrap' Interception Mechanism for Your Current Approach
Obviously, an EJB interceptor works, as you've stated.
Other than an EJB or Guice AOP interceptor... an obvious alternative would be the standard, a CDI interceptor.
But that would make it all rather circular and heavy-weight... Why use CDI just to boostrap, so that you can configure and execute to your desired DI competitor: Guice?
Suggested Alternative Solution - JAX-WS Support for Manual Endpoint Instance Initialisation
If you want POJO web services, maybe consider back-tracking a bit, instead of interceptor-driven Guice initialisation, maybe this could be what you need:
javax.xml.ws.Endpoint.publish(String address, Object implementor)
Endpoint.publish javadoc
Initialise Guice in the standard way, use injector.getInstance() to construct your endpoint instance, and then use Endpoint.publish to set the endpoint instance against the port. The following gives a good example:
Using Guice 3 with JAX-WS in Java 6 outside web container
I'm reading this book, Pro JPA2: Mastering the Java Persistance API, and I'm not getting the usefulness of the class-level annotation like in this example:
#EJB(name="cart", beanInterface=ShoppingCart.class)
public class ShoppingCartServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(true);
ShoppingCart cart = (ShoppingCart) session.getAttribute("cart");
//......
}
}
What's the point of putting that #EJB if the value of the cart variable won't be auto-injected in there and you have to init the var. yourself? Won't the code work just as well w/o that annotation? What does the annotation actually do?
I get the usefulness of the other type of annotations, like when you put it on the method or a variable, it'll auto-inject stuff. Just here, at the class level, it looks useless.
class level #EJB (or #Resource) defines that your ShoppingCartServlet depends on some EJB, in your case "cart". You need that, if you want to access to EJBs from non-managed context, like POJOs. In this case, you have to make a JNDI look-up in order to get a reference to the EJB which you can define either with ejb-ref (ejb-local-ref) descriptor, or class level #EJB annotation.
That looks like a class level annotation rather than method level, and I have no idea why one would want to annotate a servlet as EJB, but the #EJB annotation when used properly will provide that class with many different things for free, such as transactions etc...
I'm getting different instances of a #SessionScoped bean for two calls to the same user session. What can lead to this?
A bean annotated #SessionScoped is injected into a servlet, and a RESTEasy JAX-RS web service endpoint. A user logs in using HTTPS with a certificate. First call goes to the RESTEasy endpoint. The next call from the browser goes to the servlet. I'd expect the same bean instance in both calls, but they are different. ... Any ideas?
Using JBoss 7.0.1
bean:
#Stateful
#SessionScoped
public class MyBean implements Serializable { ... }
REST endpoint:
#Path("/one")
public class MyService extends JAXRSPlugin {
#Inject MyBean myBean;
...
}
Servlet:
#WebServlet(urlPatterns = "/two", asyncSupported = true)
public class MyServlet extends HttpServlet {
#Inject MyBean myBean;
...
}
Turns out the REST service methods are not really supposed to have an HttpSession to share state. REST services are supposed to be stateless. They are given #SessionScoped beans as if they were #RequestScoped by design.
It's not what I want for this case, but maybe I should just not use REST for these calls. Mainly I just wanted the handy mapping of URL paths to methods in my REST service class. Servlets don't have path-to-method-mapping like that, as far as I know.
Basically I see 3 options: (1) make of find a dispatching mechanism to use in one Servlet, (2) use multiple Servlets, or (3) mis-use the REST by abusing the #Context HttpServletRequest to get to the HttpSession. I don't like abusing APIs, so option 3 is out. CDI might make option 2 cool, but option 1 is probably more common (and so might be easier to maintain by others).
I've try to expose to the client(gwt) an aspectJ method through gwt-rpc, but the gwt client can't find the method defined in an aspect. The class that i expose implements IsSerializable and only it's method are visible to the client interface...the method added by their aspect contrariwise no. How i can fix this? thanks in advice.
p.s. i post a little example for more clarity:
this is the class...
public class Example implements IsSerializable{
private String name;
public setName(String name){
this.name=name
}
}
and this is the aspect...
privileged aspect Example_x{
public int Example.getVersion() {
return this.version;
}
}
The Example.getVersion() method is unavailable on the client side.
TNX
This won't work, as GWT needs access to the source of any Java class that is exposed to the client side. This is necessary to compile them from Java to Javascript. If you modify your classes using AspectJ, the added methods will not be visible to the GWT compiler and therefore not to the client.
I'd say AspectJ is simply the wrong tool for this task. If you want to add some methods to existing classes you could write a (possibly generic) container class that contains an instance of Example as well as the version information from Example_x.