Spring and HTTP Options request - java

As a follow up on this question, i am wondering how to handle OPTIONS request in a spring 3 mvc application.
I dont want to write an option-handling-method for every endpoint in my spring code. But the proposed mapping of an options-handler to "/**" works only for endpoints which dont have a handler already....
So i thought about using mvc interceptors to intercept OPTIONS request to handle cross-site-access stuff. but i cannot imagine that this is the best way to do this. are there any other options such as multiple handlers with different request-methods on the same path? My feeling tells me that this should actually work..(but it doesn't)!?

It looks like native Spring support for this is set for Spring 4 (Maybe).
However in the meantime I implemented the following:
Using Maven (or manually) pull in this dependancy:
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.3.2</version>
</dependency>
This has an implementation to capture all the inbound OPTIONS requests. Into the web.xml file add the following config:
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Content-Type,Accept,Origin</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The problem I've seen with the /** approach is a more specific Controller implementation will override this.

Related

Spring cloud Zuul with servlet-api 2.5

#EnableZuulProxy doesn't work under a servlet 2.5 container. Is there any workaround to get spring-cloud zuul work under a servet 2.5 container?
Also I could not find the annotation processor of #EnableZuulProxy. Please provide the class which propesses #EnableZuulProxy so that I can better understand what this annotation really does.
Spring Cloud is meant to be run on servlet 3.0. That being said, it is possible to get #EnableZuulProxy running on servlet 2.5. I had to figure out a hack for this as I had to get this working in Tomcat 6.
The main issue is due to the ZuulConfiguration.class, which has the method:
#Bean
#ConditionalOnMissingBean(name = "zuulServlet")
public ServletRegistrationBean zuulServlet() { ... }
The issue here is that ServletRegistrationBean uses javax.servlet.Registration$Dynamic, which is not available until Servlet 3.0. This results in a NoClassDefFoundError.
To work around this, use the spring-boot-legacy project to first register a DispatcherServlet. Secondly, you'll have to manually create a zuul servlet.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.dm.gateway.microservicegateway.Application</param-value>
</context-param>
<listener>
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ContextLifecycleFilter</filter-name>
<filter-class>com.netflix.zuul.context.ContextLifecycleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ContextLifecycleFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>zuul</servlet-name>
<servlet-class>com.netflix.zuul.http.ZuulServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I found the best way to remove the auto servlet registration, is to just make a verbatim copy of ZuulConfig called ZuulOverrideConfig, and remove the zuulServlet() method. This is because the ZuulProxyConfiguration extends ZuulConfiguration, and it seemed to create the bean even when i tried to override it. I'm not 100% on the mechanics behind this, so there may be a better way.
The second change I made in ZuulOverrideConfig was to call an extended implementation of ZuulFilterInitializer, called 'LegacyZuulFilterInitializer`. This is because for some reason, the Zuul servlet was being crated, and able to be invoked, but no filters were bootstrapped. This extension is a hacky way to get the filters to bootstrap.
Next, I created a copy of ZuulProxyConfiguration called ZuulLegacyProxyConfiguraiton, and had it extend ZuulOverrideConfig.class.
Finally, I annotated the Application class as follows.
#EnableCircuitBreaker
#EnableDiscoveryClient
#Import(ZuulLegacyProxyConfiguration.class)
#SpringBootApplication
public class Application {....}
After all these hacks, the implementation finally worked as expected. I wouldn't suggest using this for long, as it's pretty hacky. You won't get configuration class updates automatically when moving to new versions, and I can't guarantee that something won't break randomly!
This is using Spring Cloud 1.1.4.RELEASE
Gist of all the code.
#EnableZuulProxy is from Spring Cloud which is based on Spring Boot which is Servlet 3.0 and above. If you need to use Servlet 2.5 you can use the Netflix APIs directly.
#EnableZuulProxy is meta-annotated with #Import(ZuulProxyConfiguration.class) so I guess that's what you mean when you say "propesses"? If you don't know what an #Import is, go and read up on Spring.

i am not able to monitor the spring application through javamelody

I am not able to monitor spring application through java-melody.
Can some one help me on java-melody with spring configuration?
when I pass the URL of spring application in java-melody then I should be able to see the monitoring window.
If your application is maven managed then just add javamelody dependency to you pom
<dependency>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-core</artifactId>
<version>1.55.0</version>
</dependency>
If its not maven managed, then you can simply download and copy javamelody.jar and jrobin-x.jar to your WEB-INF/lib directory.
Once you have this, make sure you've defined java meleody filters in your web.xml
<filter>
<filter-name>monitoring</filter-name>
<filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>monitoring</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>net.bull.javamelody.SessionListener</listener-class>
</listener>
Above should give you basic monitoring at http://<host>:<port>/<context_root>/monitoring
For batch and business facaded you can follow the links as posted by #Pantelis. If you want to monitor SQLs executed, you can follow this link on the User guide - https://code.google.com/p/javamelody/wiki/UserGuide#7._JDBC
Hope this helps
JavaMelody user guide: https://code.google.com/p/javamelody/wiki/UserGuide
Basic configuration steps that you need:
Add javamelody.jar and jrobin-x.jar in your classpath
Add in your web.xml the monitoring filter and session listener as defined there: https://code.google.com/p/javamelody/wiki/UserGuide#2._web.xml_file
You can define the business facades (eg service layer) in the Spring application context: https://code.google.com/p/javamelody/wiki/UserGuide#9._Business_facades_(if_Spring)
You can also configure any batch jobs in the Spring application context: https://code.google.com/p/javamelody/wiki/UserGuide#13._Batch_jobs_(if_Quartz)
With steps 1 and 2 you will have a very basic performance report. I suggest that you read the user guide first.

Two separate Spring contexts for one webapp

I want to use two different Spring web contexts, each have own contextConfig, spring servlet and filter, that should be mapped to different urls. I have a
Standard Grails project, mapped to '/'
And an existing Spring webapp, that I want to map to /extra/
I know that I can deploy both into one Tomcat, but I'm looking for a way of making one app (one war, etc), because It can simplify our deployment and development process.
This applications don't need to share beans or anything, should be completely separate. Both have DispatcherServlet and DispatcherFilter (and both are using Spring Security, but different configuration)
How I can configure web.xml for such webapp?
I've tried to add new filter:
<filter>
<filter-name>extraSpringSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.extraSpring</param-value>
</init-param>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>extraSecurityFilterBean</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>extraSpringSecurityFilterChain</filter-name>
<url-pattern>/extra/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
and spring dispatcher servlet:
<servlet>
<servlet-name>extraSpring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>springConfigLocation</param-name>
<param-value>classpath:extra-spring-web.xml</param-value>
</init-param>
</servlet>
Where:
two context xml in classpath (inside exra library jar):
extra-spring-web.xml
extra-spring-security.xml (!!! how I should configure it?)
extra-spring-security.xml
is pretty standard Spring Security config
have configured bean extraSecurityFilterBean
have dependecy to beans from -web context (but it's not required to be)
It's semi-working now:
as I see from logs, extraSpring servlet successfully load beans from extra-spring-web.xml
but after accessing url /extra/ I got NoSuchBeanDefinitionException: No bean named 'extraSecurityFilterBean' is defined.
So, the question, how I can define context for DelegatingFilterProxy? I even tried to add this files into main context (contextConfigLocation param), it's not what i'm looking for, but it didn't work.
I've taken a look into DelegatingFilterProxy sources, but it's not clear for me how it loads the context.
As per my comment on the question, if the security filter chain is defined in extra-spring-security.xml then you need to ensure that that file is loaded by your extra DispatcherServlet in addition to extra-spring-web.xml either by <import>ing the -security file from the -web one or configuring it as:
<servlet>
<servlet-name>extraSpring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:extra-spring-web.xml
classpath:extra-spring-security.xml
</param-value>
</init-param>
</servlet>
You will also need to ensure that the security filter in the Grails application doesn't apply to /extra URIs, exactly how you do this depends on whether you're using annotations, database RequestMap entries etc.
If the modules are completely separate: the easiest way is to package them as two different webapp. Tens of different spring-based apps can run in one appserver -even on a modest developer machine- without issues.
A few questions
What does your Spring Security configuration look like?
I'm confused why the error states "No bean named 'apiservSecurityFilterChain' is defined" but the web.xml you have posted only references extraSpringSecurityFilterChain (the bean names should match or some important configuration is being left out).
Possible Answer
I'm guessing the problem is that the filter-name needs to match Spring Security's bean name (cannot know for sure without seeing the Spring Security configuration you are using). The default value used by the Spring Security namespace is springSecurityFilterChain, so try the following in the web.xml instead (notice extraSpringSecurityFilterChain changed to springSecurityFilterChain):
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.extraSpring</param-value>
</init-param>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>extraSecurityFilterBean</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/extra/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>

doubt on struts and filter

Assume it is a struts project..
the filter configuration is as follows,
<filter>
<filter-name>samplefilter</filter-name>
<filter-class>org.samplepack.SampleFilterXXX</filter-class>
</filter>
<filter-mapping>
<filter-name>samplefilter</filter-name>
<servlet-name>action</servlet-name>
</filter-mapping>
and the servlet mapping is as follows,
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
I want to know whether the samplefilter will be executed for every action class in the struts project?
can you post the situations whereever i can apply this effectively ?
The simple answer is Yes, provided that all your struts actions are accessed via the pattern *.do. This is the default configuration for Struts, so I expect that this is the case.
However as the Struts mapping us configurable, it is possible for you to define a different mapping to access a Struts action, and therefore your filter will not be picked up. But, as mentioned above, this is uncommon practice, so I expect you will be okay.

Is it possible to use a different Spring Security AuthenticationProvider in different servlets, same WAR?

I have a single WAR that runs two servlets. One provides AMF remoting to Flex clients and other SOAP/HTTP to web service clients. I currently have Spring Security configured to authenticate the Flex clients using DaoAuthenticationProvider. However, I'd like to use a different authentication provide for the SOAP/HTTP. Possibly basic authentication or some other form.
Is it possible? or do I need two WARs?
I think you'll run into problems issues with instantiating two security filter chains. The problem is that the <http> element constructs a security filter chain with a hard-wired bean name ("springSecurityFilterChain"). If you have more than one active <http> element in the webapp's spring configs, this is likely to fail.
In theory you could work around this by not using the SpringSecurity namespace and configuring the filter chains "by hand" using plain Spring XML wiring of the SpringSecurity classes. In practice, configuring SpringSecurity that way is hard.
You might be able to start two separate securityChains, I don't know if you'll run into the issues Stephen outlines.
If you filter on two different url patterns corresponding to the two servlet url patterns you should be able to filter appropriately.
<filter>
<filter-name>flexSpringSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>flexSpringSecurityFilterChain</filter-name>
<url-pattern>/messagebroker/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>webSpringSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>webSpringSecurityFilterChain</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>

Categories