I need to convert old spring xml application to java config no web.xml.
I add this class:
public class WebServletConfiguration implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(SpringConfiguration.class);
container.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(SpringConfiguration.class);
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "{com.ciro}")
public class SpringConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/static/")
.setCachePeriod(365 * 24 * 60 * 60);
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(handlerTimeLongInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/secure/**");
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/view/", ".jsp");
}
.....
}
but controller is not mapped and all request return 404. With xml configuration all works fine. What I missing?
I modified the method in this way and it works
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(SpringConfiguration.class);
rootContext.scan("com.ciro");
container.addListener(new ContextLoaderListener(rootContext));
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
Related
I'm a bit confused about adding Filters in Spring MVC with JavaConfig.
For example using the ResourceUrlEncodingFilter and the ShallowEtagHeaderFilter.
I've seen people doing this
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter("resourceUrlEncodingFilter",
new ResourceUrlEncodingFilter());
filterRegistration.setInitParameter("encoding", "UTF-8");
filterRegistration.setInitParameter("forceEncoding", "true");
filterRegistration.addMappingForUrlPatterns(null, true, "/*");
}
}
(do i have to create a Filter registration for every single Filter?)
or this
#Override
protected Filter[] getServletFilters() {
return new Filter[] { new CharacterEncodingFilter() };
}
or this
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addFilter("name", CharacterEncodingFilter.class)
.addMappingForUrlPatterns(null, false, "/*");
}
or
public class AppConfig extends WebMvcConfigurerAdapter {
/* ... */
#Bean
public ShallowEtagHeaderFilter shallowEtagHeaderFilter() {
return new ShallowEtagHeaderFilter();
}
}
or even this:
public class AppConfig extends WebMvcConfigurerAdapter {
/* ... */
#Bean
public Filter shallowEtagHeaderFilter() {
return new ShallowEtagHeaderFilter();
}
}
(seems not to work in my app)
So what is the best approach for adding Filters and keep code clean?
(What are the differences)
I have two DispatcherServlets and I want to have different contexts for them. First servlet should be secured with spring security and second servlet should not use security at all.
I register servlets as follows:
#SpringBootApplication(exclude = {DispatcherServletAutoConfiguration.class})
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public ServletRegistrationBean FirstServletRegistration() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(FirstWebConfig.class, SecurityConfig.class);
dispatcherServlet.setApplicationContext(applicationContext);
ServletRegistrationBean registrationBean = new ServletRegistrationBean(
dispatcherServlet, "/api/*"
);
registrationBean.setName("firstServlet");
return registrationBean;
}
#Bean
public ServletRegistrationBean SecondServletRegistration() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(SecondWebConfig.class);
dispatcherServlet.setApplicationContext(applicationContext);
ServletRegistrationBean registrationBean = new ServletRegistrationBean(
dispatcherServlet, "/*"
);
registrationBean.setName("secondServlet");
return registrationBean;
}
}
For each of the servlets, I set the context:
#Configuration
#EnableWebMvc
#ComponentScan("com.example.app.controllers.first")
public class FirstWebConfig extends WebMvcConfigurerAdapter {
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
#Configuration
#EnableWebMvc
#ComponentScan("com.example.app.controllers.second")
public class SecondWebConfig extends WebMvcConfigurerAdapter {
}
And I want to use SecurityConfig only for "firstServlet":
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final BCryptPasswordEncoder passwordEncoder;
private final DataSource dataSource;
#Autowired
public SecurityConfig(BCryptPasswordEncoder passwordEncoder, DataSource dataSource) {
this.passwordEncoder = passwordEncoder;
this.dataSource = dataSource;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.usersByUsernameQuery(USERS_BY_USERNAME_QUERY)
.authoritiesByUsernameQuery(AUTHORITIES_BY_USERNAME_QUERY)
.dataSource(dataSource)
.passwordEncoder(passwordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated().and()
.formLogin()
.loginPage("/api/login")
.usernameParameter("username")
.passwordParameter("password")
.and()
.httpBasic().and()
.csrf().disable();
}
}
So how can I exclude use of security for "secondServlet"?
I'm trying to configure my multi-module project for using Spring without Spring MVC.
Here is the project hierarchy :
brewspberry-rpm-parent
---- brewspberry-api (containing webservices)
---- brewspberry-core (containing services and DAOs)
---- brewspberry-webapp (containing web pages, servlets, ...)
brewspberry-core is a maven dependency of webapp.
What I try to do is being able to autowire core beans in webapp. I use Java-based configuration.
Here is my Spring webapp initializer :
public class SpringWebappInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer implements
WebApplicationInitializer {
public void onStartup(ServletContext servletContext)
throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.setServletContext(servletContext);
// rootContext.setConfigLocation("net.brewspberry.util");
rootContext.register(SpringCoreConfiguration.class);
//servletContext.addListener(new ContextLoaderListener(rootContext));
getWebAppContext(servletContext);
}
private void getWebAppContext(ServletContext servletContext) {
// now the config for the Dispatcher servlet
AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
// mvcContext.setConfigLocation("net.brewspberry.util.config");
mvcContext.register(SpringWebappConfiguration.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"DispatcherServlet", new DispatcherServlet(mvcContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("*.do");
}
#Override
protected Filter[] getServletFilters() {
return null; // new Filter[] { new AuthentificationFilter() };
}
#Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return null;
}
#Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return null;
}
}
The configuration class is :
#Configuration
#EnableWebMvc
#ComponentScan({ "net.brewspberry" })
public class SpringWebappConfiguration extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/login.jsp");
}
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
I would like that servlets could inject services from Brewspberry-core module.
I tried a solution from a previous post in SO that consisted in creating an Abstract Servlet containing this :
#Override
public void init(ServletConfig arg0) throws ServletException {
// Autowire beans in webapp
final AutowireCapableBeanFactory autowireCapableBeanFactory = WebApplicationContextUtils
.getWebApplicationContext(servletContext)
.getAutowireCapableBeanFactory();
autowireCapableBeanFactory.autowireBean(this);
}
I tried several things but still I get a NullPointerException when getting servletContext :
from arg0.getServletContext()
by autowiring it
I precise that core configuration works in tests. The issue I got is with webapp to core configuration
Update
By removing overriden onStartup method and adding both config classes to getRootConfigClasses(), servletContext is created :
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{SpringCoreConfiguration.class, SpringWebappConfiguration.class};
}
You are extending AbstractAnnotationConfigDispatcherServletInitializer but are trying very hard not to use the way it should be used.
Replace your class with the following
public class SpringWebappInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {SpringCoreConfiguration.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {SpringWebappConfiguration.class};
}
#Override
protected String[] getServletMappings() {
return new String[] {"*.do"};
}
}
That will register all that is needed (including the proper servlet mapping) and will make the code for the servlet you already have work.
The main issue is the fact that you have overridden the onStartup method basicaly destroying all the features of the AbstractAnnotationConfigDispatcherServletInitializer. That already creates a ContextLoaderListener and a DispatcherServlet for you.
I am working on a REST WebService. Now as per the requirement, I need to make the webservice secure. To do that I tired to use Spring Security in my application by enabling basic authentication. But Still i can access the app without authentication. I am using only annotations to do all the configuration. Please help me
UPDATE1: I am Deploying it on JBOSS EAP 6.4
Here is the WebSecurityConfig.java which enables the security
#Configuration
#EnableGlobalMethodSecurity
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${ldap.url}")
private String ldapUrl;
#Value("${ldap.userDN}")
private String ldapuserDN;
#Value("${ldap.password}")
private String ldapPassword;
#Override
#Order(1)
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
//.and().csrf().disable();
}
#Override
#Order(2)
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
#Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
}
#Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
LdapAuthenticationProvider provider = new LdapAuthenticationProvider(bindAuth());
return provider;
}
#Bean
public BindAuthenticator bindAuth(){
BindAuthenticator bindAuther=new BindAuthenticator(ldapContext());
String [] patternList=new String[1];
patternList[0]="cn={0},ou=ColtUsers,dc=eu,dc=colt";
bindAuther.setUserDnPatterns(patternList);
return bindAuther;
}
#Bean
public DefaultSpringSecurityContextSource ldapContext(){
DefaultSpringSecurityContextSource context= new DefaultSpringSecurityContextSource("ldap://host:390");
context.setUserDn("dndeatils");
context.setPassword("password");
return context;
}
}
here is the appconfig.java
#Configuration
#ComponentScan("package")
#EnableWebMvc
public class AppConfig {
}
Here is the WebAppInitializer
public class WebAppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.register(WebSecurityConfig.class);
ctx.setServletContext(servletContext);
Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.addMapping("/*");
dynamic.setLoadOnStartup(1);
}
}
You need to add DelegatingFilterProxy in your WebAppInitializer
public class WebAppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.register(WebSecurityConfig.class);
ctx.setServletContext(servletContext);
// This ContextLoaderListener
servletContext.addListener(new ContextLoaderListener(ctx));
// This Filter
servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain")).addMappingForUrlPatterns(null, false, "/*");
Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.addMapping("/*");
dynamic.setLoadOnStartup(1);
}
}
I have a problem with UTF-8 character (for example ěčžýáí). I find some solutions on Stack Overflow but it doesn't work for me. Here is my Conf class. I'm not using web.xml, everything is via annotation.
#Configuration
#EnableWebMvc
#Import({ SecurityConfig.class })
#ComponentScan(basePackages = "cz.prosvaly")
public class AppConfig {
#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() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
#Bean(name="multipartResolver")
public CommonsMultipartResolver multipartResolver(){
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(10000000);
return multipartResolver;
}
}
Here is my filter for encoding:
public class AppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(container);
container.addListener(new ContextLoaderListener(ctx));
FilterRegistration.Dynamic fr = container.addFilter("encodingFilter",
new CharacterEncodingFilter());
fr.setInitParameter("encoding", "UTF-8");
fr.setInitParameter("forceEncoding", "true");
fr.addMappingForUrlPatterns(null, true, "/*");
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
Dispatcher config:
#Configuration
public class DispatcherConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
// registry.addResourceHandler("/css/**").addResourceLocations("/resources/css/");
// registry.addResourceHandler("/html/**").addResourceLocations("/html/");
// registry.addResourceHandler("/images/**").addResourceLocations("/images/");
}
}
Spring security
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).
usersByUsernameQuery("select username,password, enabled from admin where username=?").
authoritiesByUsernameQuery("select username, role from user_roles where username =? ")
.passwordEncoder(new Md5PasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.and().formLogin()
.loginPage("/login").defaultSuccessUrl("/admin/goods").failureUrl("/login?error")
.usernameParameter("username").passwordParameter("password")
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/login?logout")
.and().csrf();
}
}
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
//do nothing
}
In form that I'm sending on server I have this taglib:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
I tried update in Tomcat this row:
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
But when I submit the form I see this in the log
....type for žÄáÞÃé
(Posted on behalf of the OP:)
I have to deleted SpringSecurityInitializer and create filter via the following code in in AppInitializer:
fr = container.addFilter("springSecurityFilterChain",
new DelegatingFilterProxy());
fr.addMappingForUrlPatterns(null, true, "/*");