Cannot register a filter to the CXF bundle in my bundle - servlets

I am having trouble using the Pax Web Whiteboard service to register a javax.servlet.Filter to a running JaxRS endpoint registered through CXF. I have tried a few different approaches, namely registering the Filter as a service, and using the org.ops4j.pax.web.service.WebContainer to register the filter directly.
For my test, i booted karaf, and installed pax-web, webconsole, cxf and the pax-web whiteboard service.
I the registered a bundle with a blueprint:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
">
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
<jaxrs:server id="webfiltersample" address="/webfilter">
<jaxrs:serviceBeans>
<ref component-id="serviceBean" />
</jaxrs:serviceBeans>
</jaxrs:server>
<service id="servletFilterService" interface="javax.servlet.Filter">
<service-properties>
<entry key="filter-name" value="BasicWebFilter"/>
<entry key="urlPatterns" value="/*"/>
<entry key="initParams" value=""/>
</service-properties>
<bean class="test.webfilter.BasicWebFilter"/>
</service>
<bean id="serviceBean" class="test.webfilter.WebFilterSample" init-method="init" destroy-method="destroy">
<property name="bundleContext" ref="blueprintBundleContext"/>
</bean>
</blueprint>
However, this filter is never called. I have tried both using servlet names and urlpatterns, going so far as to attempt the urlpattern /*
I then tried a slightly different approach, removing the service declaration from the blueprint, and adding the filter directly though the init method of the blueprint instead:
public void init(){
logger.info("Starting Sample");
filter = new WebFilter();
ServiceReference<WebContainer> ref = bundleContext.getServiceReference(BasicWebFilter.class);
WebContainer container = bundleContext.getService(ref);
logger.info("Registering "+ filter + " with "+ container);
container.registerFilter(filter, new String[]{"/cxf/*"}, new String[]{""}, null, null);
bundleContext.ungetService(ref);
}
The method is indeed called, as reflected by the log statements, but the filter is still not executed.
So am i completely wrong in how this works? My "Application" is really just an endpoint registered to the CXF servlet. This part is working, and i can call the REST services defined therein. But no matter what i do, the filter is not executing. I am working with a few libraries here that i don't really know that well (Servlets/Filters, Pax-Web and the Writeboard extender) do i have no idea why exactly this isn't working? My guess is that there are different httpcontexts for each bundle, and that i can't simply register a filter for another bundle (CXF) in my own test bundle.
If this is true, can someone tell me how to properly go about this problem? I could get the CXF bundles bundlecontext and register the filter to that, but that seems like a terrible horrible hack.
If that is NOT the case, can someone tell me why this is not working?

You are right, every bundle should have it's own httpContext. With Pax-Web it's possible to have shared httpContextes. For this you need to enable it for the bundle initially registering the httpContext. Though in this case it's the cxf bundle that does take care of it. As the shared context is a pax-web only feature (till v6 where OSGi R6 is implemented), this won't be added to cxf as cxf tends to rely on the smallest possible solution, which is the HttpService.
Basically even though it's possible to share httpContextes with different bundles, it's not possible for you with this scenario.

I propose to use JAAS instead of shiro as a way to login and store the authentication information. You can then use this in shiro as well as in other security implementations to do the authorization.
For CXF there is a JAASLoginFeature. It can receive basic auth as well as UserNameToken. See https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=42568988
This also has the advantage that it works the same way as the standard karaf authentication. So by default you can define users and groups in etc/users.properties but you can also for example attach karaf to ldap.
If you use blueprint then you can use blueprint-authz do role based authorization using annotations. See https://github.com/apache/aries/tree/trunk/blueprint/blueprint-authz and https://github.com/apache/aries/blob/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/authz/testbundle/impl/SecuredServiceImpl.java

Related

spring security logout trigger

I want to remove logged out user from a Hashmap I have for logged in users but I don't find the way to do this as when I press the logout link. It just redirected to login page.
In spring security I have
<logout invalidate-session="true"
logout-success-url="/"
logout-url="/logout.htm"/>
logout link is like
Logout
When I press this link it just go to my login mapping
#RequestMapping("login")
public ModelAndView login(){}
and when I try to get user detail using
SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
it returns me anonymous user. So how can I get the logged out user detail.
Please let me know if you need more details.
Add an implementation of org.springframework.security.web.authentication.logout.LogoutSuccessHandler interface as a bean to your security context.
Then you can use it:
<logout success-handler-ref="yourLogoutSuccessHandler" />
EDIT.
As mentioned by Marcel this solution will not work out of the box because you can't mix success-handler-ref and logout-success-url attributes (reference). I prefer slightly different solution : instead of inheritance, you can use composition:
Prepare configuratio for SimpleUrlLogoutSuccessHandler bean.
Set up logout-success-url via corresponding defaultTargetUrl property.
Inject SimpleUrlLogoutSuccessHandler bean into your CustomUrlLogoutSuccessHandler using LogoutSuccessHandler interface and call it after doing your stuff.
Advantage is that you will be less coupled with a framework code. So you will have less problems in a case of migration from Spring Security 3.1 to Spring Security Y.Y
The hint about the LogoutSuccessHandler is correct. However, you have to consider that configuring success-handler-ref and logout-success-url are mutually exclusive if I'm not mistaken. Hence, you need to implement the forwarding to URL manually in your success handler. Pointer: https://stackoverflow.com/a/6770785/131929
Authentication authentication = SecurityContextHolder.getContext().getAuthentication()
authentication.getName()
In your applicationContext-security.xml file add the success-handler like below
< logout logout-url="/resources/j_spring_security_logout" success-handler-ref="com.mycompany.security.SpringSecurityLogoutHandler" />
Create the Class which will be implemneting org.springframework.security.web.authentication.logout.LogoutHandler interface and in it's logout method do all the stuff you want at the time of logout.

How do you create CouchDB Views using Spring Bean Deployment with LightCouch

I am using Spring-MVC LightCouch and CouchDB and I have custom Views that need to be inserted into the DB on deployment. I have found the LightCouch has a method for pulling documents "from desk" as noted on their website:
DesignDocument designDoc = dbClient.design().getFromDesk("example");
Response response = dbClient.design().synchronizeWithDb(designDoc);
This Works good from within JAVA code, however I need to be able to do it in the Spring ApplicationContext.xml I have more than one so I would like to mimick the call of:
dbClient.dessign().synchronizeAllWithDB()
How would I do this in the bean definition of the ApplicationContext I already have this:
<bean id="dbClient" class="org.lightcouch.CouchDbClient" lazy-init="false" destroy- method="shutdown">
<constructor-arg value="couchdb.properties" />
</bean>
It seems you can't do it with Spring xml config, as the init method falls under a different instance; that is returned by the call to design() factory method. Maybe you can try Java code equivalence, i.e. #PostConstruct.
I ended up having to make a bean that synchronized the database on init and created that when the app starts

What does <mvc:annotation-driven /> do?

I use filenames in my REST API (example: GET http://xxx/api/myImage.jpg)
problem is #PathVariable dropped ".jpg".
this problems already asked few times in here and answered. but not worked to me.
so I searched then found at the
https://jira.springsource.org/browse/SPR-6524
"... is simply not supposed to be combined with manual DefaultAnnotationHandlerMapping instances; this is designed as an either-or choice at present, quite similar to and ."
"mvc namespace are make simplifed configurations".
Real question is mvc what does do? and changed?
I found my self these things..
intercepter configuration changed. (mvc namspace required in bean configuation)
useDefaultSuffixPattern is not working.
adds JSON message converter. if jackson library is available
#PathVariable arguments are auto added to model
Any others?
Thanks in advance!
The mvc:annotationDriven tag essentially sets you your Spring context to allow for dispatching requests to Controllers.
The tag will configure two beans DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter.
You can find more information from the spring documents:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html
Before I provide certain points let me clear up the answer provided by Roy is not accurate. You don't have to provide mvc:annotation-driven tag to instantiate default beans. This tag can be used Spring 3.0+ to enable new feature introduced from Spring 3.0
(Do not use it if you want backward compatibility, especially if you are using old controller based classes like MultiActionController, SimpleFormController)
Now lets come to what this tag actually does -
Prior to Spring 3.1 default beans used where
DefaultAnnotationHandlerMapping
AnnotationMethodHandlerAdapter
AnnotationMethodHandlerExceptionResolver
These are deprecated in Spring 3.1 and if you use above mentioned tag it will be replaced by -
RequestMappingHandlerMapping
RequestMappingHandlerAdapter
ExceptionHandlerExceptionResolver
DefaultAnnotationHandlerMapping decided which controller to use and the AnnotationMethodHandlerAdapter selected the actual method that handled the request. RequestMappingHandlerMapping does both the tasks. Therefore the request is directly mapped right to the method.
There are other infrastructure beans that are instantiated by these tag (chained in addition to defaults) like - MappedInterceptor, ConfigurableWebBindingInitializer, SessionFlashManager, ContentNegociationManager etc. I am not going to explain these :) as they each are long answers themselves, so google it for more info.
PS : And yes Spring 3.1+ automatically expose #PathVariables to the model. Also you have mvc:interceptors tag. But I think it is not related to <mvc:annotation-driven />. I would highly recommend read - http://spring.io/blog/2009/12/21/mvc-simplifications-in-spring-3-0/
To enable MVC Java config add the annotation #EnableWebMvc to one of your #Configuration classes:
#Configuration
#EnableWebMvc
public class WebConfig {
}
To achieve the same in XML use the
mvc:annotation-driven
element in your DispatcherServlet context (or in your root context if you have no DispatcherServlet context defined):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven/>
</beans>
The above registers a RequestMappingHandlerMapping, a RequestMappingHandlerAdapter, and an ExceptionHandlerExceptionResolver (among others) in support of processing requests with annotated controller methods using annotations such as #RequestMapping, #ExceptionHandler, and others.
For details refer the below link :
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config
mvc:annotation-driven tag do extra work from context:component-scan tag
The tag registers the Handler Mapping and Handler Adapter required to dispatch requests to your #Controllers:
tag helps registering the following components.
DefaultAnnotationHandlerMapping - This is a HandlerMapping implementation which maps the HTTP requests to the handler methods defined using the #RequestMapping annotation.
AnnotationMethodHandlerAdapter - It is responsible for scanning the controllers to identify methods (and parameters) annotated with #MVC annotations. It scans and caches handler methods annotated with #RequestMapping. Also handles the #RequestParam, #ModelAttribute, #SessionAttributes and #InitBinder annotations.
ConfigurableWebBindingInitializer - The initializer for the Web Data Binder. Helps in declaratively configuring the Web Binder with validators, conversion services, property editors, etc.
LocalValidatorFactoryBean - Implements the validator interface and enables JSR303 validation. This is injected into ConfigurableWebBindingInitializer.
FormattingConversionServiceFactoryBean - A conversion factory that returns conversion services for basic objects like date and numbers. This factory is again injected into ConfigurableWebBindingInitializer.
Message Converters
ByteArrayHttpMessageConverter - A HTTP request message converter that reads a HTTP message body and returns a byte stream. It can also read a byte stream and construct a response body. Used for receiving and sending documents like PDF, XLS, etc.
StringHttpMessageConverter - A HTTP request message converter that reads a plain text request body and binds it to a String object. And vice-versa with response.
FormHttpMessageConverter - A HTTP request message converter that reads a form encoded request body and binds it to a form Binding object.
SourceHttpMessageConverter - A HTTP request converter that converts a XML message body to/from Binding Object.
If we do not use mvc:annotation-driven tag then we have to do register these components manually in xml file in order to use them , which results in too much extra work.

Accessibility of a servlet class from within an external web.xml file

I have two web applications.But only one among them includes Java servlet class.I want to access that servlet class from within the web.xml file of other application.Is it possible?.If yes,How will be it possible?.
You can't do that in the web.xml. You can however create a new servlet which in turn redirects/forwards the request to the servlet of the other webapplication. Redirecting is easy, just let the URL point to the particular servlet.
response.sendRedirect("/otherwebapp/theservlet");
Forwarding requires a bit more work. This is by default not possible due to security restrictions. First you need to configure the servletcontainer to enable cross context access between the webapplications in question. It's unclear which one you're using, so here's just a Tomcat targeted example so that you understand in what direction you should look for your own servletcontainer: for the both webapps, you need to set the crossContext attribute of the <Context> element to true:
<Context crossContext="true">
This way you can obtain the other context by ServletContext#getContext() inside a servlet:
ServletContext othercontext = getServletContext().getContext("/otherwebapp");
Finally you can forward the request through it as follows:
othercontext.getRequestDispatcher("/theservlet").forward(request, response);

How to obtain OSGi service references from a Servlet that is registered in OSGi HttpService?

It seems natural that a HttpServlet running in OSGi environment (i.e. registered in OSGi HttpService) would want to call some OSGi services to accomplish it's tasks. The question is how to obtain references to these OSGi service inside the servlet.
One way would be to inject dependencies into the HttpServlet instance that is being registered to the OSGi HttpService like this:
MyServlet servlet = new MyServlet();
servlet.setFooService(fooService);
httpService.registerServlet("/myservlet", servlet, initparams, context);
I'm not sure if this is a valid approach since in non-OSGi environment the servlet life-cycle is managed by the Web Container and hence the service reference would not be injected for the servlet instances created later on.
There is another way to solve this when using PAX Web as an implementation of the OSGi HttpService. PAX Web exports the OSGi BundleContext into the ServletContext as a special attribute "osgi-bundlecontext". The BundleContext can then be used to obtain necessary service references:
public void init(ServletConfig servletConfig) throws ServletException {
ServletContext context = servletConfig.getServletContext()
BundleContext bundleContext =
(BundleContext) context.getAttribute("osgi-bundlecontext");
ServiceReference serviceRef =
bundleContext.getServiceReference("com.foo.FooService")
}
However this approach is rather ugly and ties you to a concrete implementation of the OSGi HttpService. Do you know any other (and possibly better) solution to this problem?
If you use a setter for the dependency on the service, as you have shown, it can work outside of OSGi as well. You just need to use some other dependency injection mechanism. If there is none, you could provide a subclass that initializes the servlet using JNDI lookups or from the servlet context.
public class MyServlet_AdapterForMissingDI extends MyServlet{
public void init(ServletConfig config){
setFooService(getItFromSomewhere());
}
}
The point being that if you have DI capabilities that can inject setFooService, you can just use the same servlet in OSGi and elsewhere, if you do not (and still want to support this case), you provide an adapter.
On a related note, check out Felix SCR to configure your object's dependencies, and Pax Web Extender Whiteboard, which takes care of hooking your servlet up with the HttpService.
Specifically, without SCR and Whiteboard, you need to think about the case when the fooService becomes unavailable later, or the HttpService gets started after your servlet.
In these cases your servlet would have a reference to a dead service that prevents the bundle from being garbage-collected, or your servlet would not be registered with the HttpService.
Update: Here is the SCR descriptor I use for one of my servlets. SCR handles servlet instantiation, life-cycle, registration (via Whiteboard), and dependencies. There is no OSGi-specific code in the servlet. There is not even the need for a BundleActivator anymore (SCR registers all services):
<component name="oracle.statusServlet" >
<implementation class="mypackage.DataSourceStatusServlet"/>
<property name="service.description" value="Oracle DataSource status servlet" />
<property name="alias" value="/OracleDataSourceStatus" />
<property name="servlet-name" value="Oracle DataSource status servlet" />
<service>
<provide interface="javax.servlet.Servlet" />
</service>
<reference name="DATASOURCES"
interface="javax.sql.DataSource"
cardinality="0..n" policy="dynamic"
bind="bindDataSource" unbind="unbindDataSource"/>
</component>
The dependencies for the servlet are specified in the reference tag. SCR will do the service lookup and binding.
May be an old post and you already might have got the answer..
Are you launching felix or whatever OSGi container yourself. If that is the case you can set the bundle context as an attribute to the servlet context.
Whats wrong in using an http service by PAX. ultimately the thread management and other aspects are taken care of by the servlet container in which you run this http service.
You could inject the services into some object, which is then queried by the servlets.

Resources