Adding SecurityWebApplicationInitializer to existing Spring app - java

I try to follow answers to this question, but still cannot make it work.
I have following Java config classes:
public class MyWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(WebAppConfiguration.class);
container.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
And for security:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(WebSecurityConfiguration.class);
}
}
The problem is I get exception like that on startup:
java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
Without SecurityWebApplicationInitializer class it starts up and works fine except of the fact that Spring Security doesn't work.
I understand that the problem is that SecurityWebApplicationInitializer injects it's own context. But then what is the right way to make the Spring Security work for my case?
Thank you.

Related

Programmatic integration of Spring 4 and jersey [duplicate]

This question already has an answer here:
Combining Spring project and Jersey
(1 answer)
Closed 6 years ago.
How do I autowire my spring beans in a jersey resource?
I'm trying to cobble together a jersey app which uses spring to initialise the fields in the jax-rs resources. From googling, it seems possible but they are always null. My beans get created but not injected.
My REST resource
#Path ("/clips")
#Component
public class ClipStreamService {
#Autowired
private ClipHandler clipHandler;
#GET
public Response defaultGet() {
Clip clip = clipHandler.getDefault(); <-- ***** throws an NPE *****
The spring WebInitilizer
public class SpringWebInitialiser implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RootConfig.class);
rootContext.setServletContext(container);
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(WebConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
And the bean config (note I've also tried adding the bean to RootConfig)
#Configuration
#ComponentScan ({ ... })
public class WebConfig {
#Bean
public ClipHandler clipHandler() {
return new ClipHandler();
}
}
You can manually invoke autowiring in your jersey resource like below:
#Context
private ServletContext servletContext;
#PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, servletContext);
}

Restful App with Spring MVC - Ambiguous handler methods error

I'm trying to build a Restful webapp using Spring MVC 4.
But I'm got this error "Ambiguous handler methods mapped for HTTP".
In my controller I have this endpoints:
GET /people/
GET /people/{id}
POST /people/
DELETE /peope/{id}
PUT /people/{id}
I think this error occurs because I have something wrong in my configuration.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.myapp.rest.controller" })
public class MVCConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/site/**").addResourceLocations("/WEB-INF/site/**");
}
}
And this
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext)
throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.myapp.config");
return context;
}
}
Thank you all

Can not assign ServletContext spring 3

I am trying to use servletcontext.getRealPath in my Util class to load a file resource (Not part of unit testing) but it does not work.
I tried both to use "implements ServletContextAware":
#Component
public class Utils implements ServletContextAware{
private ServletContext servletContext;
#Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
System.out.println("**** "+servletContext);
}
}
Which throws NPE since servletcontext is not assigned by spring.
And the #Autowired route:
#Component
public class Utils{
#Autowired
private ServletContext servletContext;
Which throws NoSuchBeanDefinitionException when tomcat is being starting:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.servlet.ServletContext] found for dependency: expected at le
ast 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I am adding the my initialization code in case I am doing something wrong which prevents Spring to inject the right bean.
public class WebAppInitializer implements WebApplicationInitializer {
private static Logger LOG = LoggerFactory.getLogger(WebAppInitializer.class);
#Override
public void onStartup(ServletContext servletContext) {
WebApplicationContext rootContext = createRootContext(servletContext);
configureSpringMvc(servletContext, rootContext);
FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", CORSFilter.class);
corsFilter.addMappingForUrlPatterns(null, false, "/*");
// configureSpringSecurity(servletContext, rootContext);
}
private WebApplicationContext createRootContext(ServletContext servletContext) {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
// rootContext.register(CoreConfig.class, SecurityConfig.class);
rootContext.register(CoreConfig.class);
rootContext.refresh();
servletContext.addListener(new ContextLoaderListener(rootContext));
servletContext.setInitParameter("defaultHtmlEscape", "true");
return rootContext;
}
CoreConfig.class:
#Configuration
public class CoreConfig {
#Bean
public CaptionFixture createCaptionFixture() {
return new CaptionFixture();
}
#Bean
public Utils createUtils () {
return new Utils();
}
}
Utils is the class with the servlet context.
I have looked at the suggested answers: here and here and it didnt work.
The issue is that you are calling refresh() without a ServletContext being registered, so none is available when the beans are initialized.
Get rid of this call
rootContext.refresh();
The ContextLoaderListener will take care of calling refresh(). The constructor javadoc explains what happens when the ApplicationContext passed as an argument isn't refreshed.

Why doesnt my Spring Security authentication work?

I have the following configuration placed in /src/main/java/com/dog/bootstrap:
#EnableWebSecurity
#Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("hello");
auth.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("USER");
}
}
and I am loading it as follows:
public class WebInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.scan("com.dog.bootstrap");
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(dispatcherContext));
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
Set<String> mappingConflicts = dispatcher.addMapping("/");
if (!mappingConflicts.isEmpty()) {
throw new IllegalStateException("'dispatcher' could not be mapped to '/' due " +
"to an existing mapping.");
}
}
My controller:
#Controller
public class DogController {
#RequestMapping(value = {"/dog"}, method = RequestMethod.GET)
#ResponseBody
public String getSource(#PathVariable("domain") String domain) throws Exception {
return "dogs";
}
}
When I startup my app, I do see hello being printed, so configure(AuthenticationManagerBuilder auth) is being called. However, none of my endpoints are requiring me to enter a login page. When I go to localhost:8080/dog it outputs dogs without asking me to authenticate myself.
You're not actually including the filter chain, as described in the last step of this guide. Try adding this default initializer, which maps to /*:
#Component public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}

Why doesn't component scan pick up my #Configuration?

I have a config file like
package com.mypackage.referencedata.config;
#Configuration
#ComponentScan ("com.mypackage.referencedata.*")
public class ReferenceDataConfig {
In a spring xml if I have
<context:component-scan base-package="com.mypackage.referencedata.config.*" />
it does not get loaded.
If I use
<context:component-scan base-package="com.mypackage.referencedata.*" />
it works.
What gives? I'd expect the 1st to work as well.
<context:component-scan base-package="com.mypackage.referencedata.config.*" />
Will scan packages inside com.mypackage.referencedata.config as it is package.
com.mypackage.referencedata.config
Will work fine.
You don't need to scan the #Configuration class in component scan in SpringFramework. But you need to register it in the Application Initializer class of your web application that defines the configuration required as in web.xml file. You need to implement WebApplicationInitializer interface there and define onStartup method.
In that onStartup method you need to register your #Configuration class to the rootContext of your web application. Please take a look at the following code snippet.
1. The class that works as web.xml
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("/");
}
}
2. The #Configuration class of web application holds the beans and other setups.
#EnableWebMvc
#Configuration
#ComponentScan(basePackages={"com.abcprocure.servicerepo.controller", "com.abcprocure.servicerepo.model", "com.abcprocure.servicerepo.service"})
public class DispatcherConfig extends WebMvcConfigurerAdapter {
//Registers the url paths for resources to skip from spring. Eg. JS, CSS and images.
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// TODO Auto-generated method stub
registry.addResourceHandler("/js/**").addResourceLocations("/js/**");
registry.addResourceHandler("/html/**").addResourceLocations("/html/**");
}
//Defines the ViewResolver that Spring will use to render the views.
#Bean
public ViewResolver viewResolver() {
System.out.println("Inside View Resolver...");
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
//Defines the DataSource to use in the application.
#Bean
public DataSource dataSource() {
System.out.println("Inside DataSource bean creation....");
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dataSource.setUrl("jdbc:sqlserver://192.168.100.131;databaseName=test");
dataSource.setUsername("egptender");
dataSource.setPassword("egp#123");
return dataSource;
}
//Defines the Hibernate's SessionFactory.
#Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource()).addAnnotatedClasses(Services.class, Operations.class, OperationParameters.class, ServiceModels.class, Businesslogic.class,TblFormMaster.class,TblFormBuilder.class);
builder.setProperty("hibernate.dialect", "org.hibernate.dialect.SQLServerDialect");
builder.setProperty("hibernate.show_sql", "true");
return builder.buildSessionFactory();
}
}
Hope this helps you. Cheers.
If you are using maven, check if you have correct dependencies

Categories