Spring MVC - DispatcherServlet by annotations - java

I got spring MVC application.
It runs on Tomcat 7.
By now i got this part in my web.xml file:
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/app-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
Is there any way to init it by annotations? I got a MainSettings.java class where all my beans are initialyzed by #Bean annotation. So how do i initDispatherServlet there?

Here is the example with comments. Hope this helps you.
public class ApplicationInitializer implements WebApplicationInitializer {
//Called first when the application starts loading.
public void onStartup(ServletContext servletContext)
throws ServletException {
System.out.println("Inside application initializer...");
//Registering the class that incorporates the annotated DispatcherServlet configuration of spring
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(DispatcherConfig.class);
//Adding the listener for the rootContext
servletContext.addListener(new ContextLoaderListener(rootContext));
//Registering the dispatcher servlet mappings.
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}

Writing this because Japs's answer leads to creation of another context, which doesn't see the contents of the security context.
public class WebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
private static final Log LOGGER = LogFactory.getLog(WebInitializer.class);
#Override
protected Class<?>[] getRootConfigClasses() {
/* this is where you will return you config class
* your root config class should #Import other configs
* to make them work without needing them to add there
*/
return new Class[] { ViewConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[0];
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}

Related

Spring Security config - 403 forbidden

I Use spring 5.0.7.RELEASE and I need to add basic authentication for my spring application and this is a pretty old application. That is why it uses the old way of registering the config classes. I have added the SecurityConfig class and imported it in the SpringMvcConfig as shown below
#Configuration
#EnableWebMvc
#ComponentScan( basePackages = {
"com.test" },
excludeFilters = {
#ComponentScan.Filter( Configuration.class )
} )
#ImportResource("classpath:/spring-context.xml")
#EnableSwagger2
#Import({SwaggerConfig.class, SecurityConfig.class})
public class SpringMvcConfig extends WebMvcConfigurationSupport {
#Autowired private ApplicationContext applicationContext;
private static final String[] RESOURCE_BUNDLES = new String[] { "MessageResources" };
private static final String[] YAML_RESOURCE_BUNDLES = new String[] { "messages" };
/**
* Configures the Jackson object mapper
*/
#Bean( name = "objectMapper" )
public ObjectMapper getObjectMapper( JacksonService jacksonService ) {
return jacksonService.getObjectMapper();
}
/**
* Configures the ApplicationContextProvider
*/
#Bean( name = "applicationContextProvider" )
public ApplicationContextProvider getApplicationContextProvider() {
return new ApplicationContextProvider();
}
}
and here is the web.xml
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.test.SpringMvcConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Spring Security Configuration -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
and here is my SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication()
.withUser("test")
.password("testpwd")
.roles("USER");
}
}
I get a 403 forbidden The server understood the request but refuses to authorize it. I also added
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}

Disable Swagger in Jersey 2.X

I am following the swagger tutorial to swaggerize my web application.
. I am using package scanning and Swagger's BeanConfig for swagger initialization. Is there a way to disable swagger in specific environment (e.g. production)? There are some discussion talking about disabling swagger with SpringMVC
Here is my web.xml
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
io.swagger.jaxrs.listing,
com.expedia.ord.ops.rest
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Hooking up Swagger-Core in your application -->
<servlet>
<servlet-name>SwaggerServlet</servlet-name>
<servlet-class>com.expedia.ord.ops.util.SwaggerServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>SwaggerUI</servlet-name>
<jsp-file>/SwaggerUI/index.html</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>SwaggerUI</servlet-name>
<url-pattern>/api/docs/*</url-pattern>
</servlet-mapping>
Here is my Swagger servlet:
public class SwaggerServlet extends HttpServlet
{
static private final String[] SCHEMES = {"http"};
#Value("${swagger.enable}")
private boolean enableSwagger;
#Value("${swagger.resource.package}")
private String resourcePackage;
#Value("${swagger.host}")
private String host;
#Value("${swagger.basePath}")
private String basePath;
#Value("${swagger.api.version}")
private String version;
#Override
public void init(final ServletConfig config) throws ServletException
{
super.init(config);
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
final BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion(version);
beanConfig.setSchemes(SCHEMES);
beanConfig.setHost(host);
beanConfig.setBasePath(basePath);
beanConfig.setResourcePackage(resourcePackage);
beanConfig.setScan(enableSwagger);
}
}

Can't login with Java Configuration and Spring Security 3.2

I'm having trouble after switch my application to Spring security 3.2 and Java Configuration. Originally it was configured with xml but once I've made all the changes to use annotations every time I try to access to localhost:8080/mysite/login I have this error "No mapping found for HTTP request with URI [/mysite/login] in DispatcherServlet with name 'mvc-dispatcher". This is my configuration:
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
AppConfig.java
#EnableWebMvc
#Configuration
#ComponentScan({ "com.mypackages.*" })
#Import({ DatabaseConfig.class, SecurityConfiguration.class, SocialConfig.class })
#PropertySource(value = {"classpath:/mysite.properties"})
public class AppConfig extends WebMvcConfigurerAdapter {
//in this class I define the viewResolver, messageSource, localeResolver, some properties, etc, but I don't think they would be necessary for my problem
}
"configure" method at SecurityConfiguration.java
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login").defaultSuccessUrl("/welcome")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
.and()
.authorizeRequests()
.antMatchers("/welcome*").authenticated()
.and()
.rememberMe()
.and().headers().xssProtection().frameOptions().httpStrictTransportSecurity()
.and()
.apply(new SpringSocialConfigurer());
}
web.xml
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
com.myapp.config.AppConfig
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.myapp.config.AppConfig</param-value>
</context-param>
As far as I understand, with the login page setted in the "configure" method (SecurityConfiguration.java) should be enough to show the login page when I access to localhost:8080/mysite/login, I've been reading some examples I don't think the error is on the security configuration, am I missing something?.
Any help will be appreciated
UPDATE
I've been searching and it seems like my error was to include both web.xml and an extension of AbstractAnnotationConfigDispatcherServletInitializer so I decided to remove the web.xml, and modify SpringMvcInitializer:
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class, SecurityConfiguration.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { DatabaseConfig.class };
}
But still have the same error No mapping found for HTTP request with URI [/siteserver/login] in DispatcherServlet with name 'dispatcher', pleeeaaaase does anybody has a clue about what's going on?
If you are using a spring security, i think you should also configure application context.xml which should be in your WEB-INF folder.
Change the location of your context config. I believe it should be your applicationContext.xml and all the confifuration will go inside that.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
You can also try adding the listener class in your web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

Spring MVC 4.0 - Hibernate OpenSessionViewFilter in WebConfig

Basically, how can I do this:
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
in WebInitializer?
Beacuse if a write:
#Override
protected Filter[] getServletFilters() {
return new Filter[] {
new SpringSecurityFilterChain(), new OpenSessionViewFilter()
};
}
it doesn't take any effect.
I think the url-pattern is missing.
Thanks in advance!
This is what we have done
public class DispatcherServletInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
public void onStartup(ServletContext servletContext)
throws ServletException {
servletContext
.addFilter("securityFilter",
new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
//add other filters like this
super.onStartup(servletContext);
}
}

How can implement AbstractAnnotationConfigDispatcherServletInitializer for java config on my spring 3.2 and hibernate 4 integration project?

On my application, I am using spring 3.2, jsf 2.1 and hibernate 4 integration. I want to replace configuration xml files to java config. For that I am focusing on AbstractAnnotationConfigDispatcherServletInitializer and WebMvcConfigurerAdapter section.
web.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name />
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<description>generated-persistence-filter</description>
<filter-name>MySQLFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
<init-param>
<param-name>entityManagerFactoryBeanName</param-name>
<param-value>MySQL</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MySQLFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/jsf/login.xhtml</location>
</error-page>
</web-app>
how can implement context-param , welcome-file-list and error-page on javaconfig class.
My javaconfig class is,
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/", "/*", "*.faces", "*.xhtml" };
}
#Override // for representing Faces Serelet context, is it correct?
public void onStartup(ServletContext servletContext)
throws ServletException {
servletContext.addServlet("Faces Servlet", "javax.faces.webapp.FacesServlet");
super.onStartup(servletContext);
}
#Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
OpenEntityManagerInViewFilter openEntityManagerInViewFilter = new OpenEntityManagerInViewFilter();
openEntityManagerInViewFilter.setPersistenceUnitName("MySQL");
return new Filter[] { characterEncodingFilter, openEntityManagerInViewFilter, new org.primefaces.webapp.filter.FileUploadFilter()};
}
}
and
#Configuration
#EnableWebMvc
#Import(DatabaseConfig.class)
#ComponentScan(basePackages = { "com.shiv.ShivCDB.web.jsf", "com.shiv.ShivCDB.service" })
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
#Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.put("org.springframework.web.servlet.PageNotFound", "p404");
mappings.put("org.springframework.dao.DataAccessException", "dataAccessFailure");
mappings.put("org.springframework.transaction.TransactionException", "dataAccessFailure");
b.setExceptionMappings(mappings);
return b;
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(StringUtils.parseLocaleString("en"));
return cookieLocaleResolver;
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages/messages", "classpath:messages/validation");
// if true, the key of the message will be displayed if the key is not
// found, instead of throwing a NoSuchMessageException
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
// # -1 : never reload, 0 always reload
messageSource.setCacheSeconds(0);
return messageSource;
}
}
you need to register spring ContextLoaderListener in your onStartup method, for xml configuration:
public void onStartup(ServletContext servletContext) {
XmlWebApplicationContext root = new XmlWebApplicationContext
root.setConfigLocation("/WEB-INF/applicationContext.xml")
servletContext.addListener(new ContextLoaderListener(root))
}
for java config:
public void onStartup(ServletContext servletContext) {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext
//scan the package of your #Configuration java files
root.scan("org.example.config")
servletContext.addListener(new ContextLoaderListener(root))
}
It looks like there is no annotations or java config support for welcome-file list and error-pages, you still have to define them in web.xml and servlet container will load both web.xml and WebInitializer.
If you want to entirely get rid of web.xml, you can try to implement welcome file and error page in your web framework.
--edit--
I am not familiar with jsf, you can try to add following in method onStartup :
servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "server");
servletContext.setInitParameter("com.sun.faces.expressionFactory", "com.sun.el.ExpressionFactoryImpl");

Categories