Spring Autowiring fails - spring

I have added one Listener in web.xml
<listener>
<listener-class>*.LoadCacheServlet</listener-class>
</listener>
This is servlet class
#Component
public class LoadCacheServlet implements ServletContextListener {
#Autowired
private ConnectorRepository connectorRepository;
#Override
public void contextDestroyed(ServletContextEvent arg0) {
LOGGER.info("ServletContextListener destroyed----------------------------");
}
// Run this before web application is started
#Override
public void contextInitialized(ServletContextEvent arg0) {
LOGGER.info("ServletContextListener startedddd---------------------------------");
connectorRepository.callMe("xys");
}
}
On tomcat startup. contextInitialized method gets exceuted but connectorRepository is not initailized. ConnectorRepository is an interface and in other parts of application its gets autowired by SpringJPA module. How to initialize it in servlet.

Related

How to trigger listener after 1 particular bean initialized

Does anybody know if it is possible to create Spring Boot listener that would be called once only 1 particular bean has been initialized?
I only know how to create listener that is triggered once all beans have been initialized:
#EventListener(ContextRefreshedEvent.class)
public void myListener(ContextRefreshedEvent event) {...}
But that listener will be triggered for every single bean in the app instead of 1 particular bean I am looking for.
Any ideas?
Here's how this could be done.
First make your bean publish an event when it's initialized by implementing InitializingBean or having a #PostConstruct method:
public class SomeBeanInitializedEvent extends ApplicationEvent {
...
public SomeBeanInitializedEvent(Object source) {
super(source);
}
}
#RequiredArgsConstructor
public class SomeBean implements InitializingBean {
private final ApplicationEventPublisher applicationEventPublisher;
#Override
public void afterPropertiesSet() {
applicationEventPublisher.publishEvent(new SomeBeanInitializedEvent(this));
}
}
Or as a #Bean method use the standard ApplicationEventPublisher available in the context:
#Bean
public SomeBean someBean(ApplicationEventPublisher publisher) {
SomeBean someBean = ...
publisher.publishEvent(new SomeBeanInitializedEvent(someBean));
return someBean;
}
Then create an event listener for your event:
private class SomeBeanInitializedEventApplicationListener implements ApplicationListener<SomeBeanInitializedEvent> {
#Override
public void onApplicationEvent(SomeBeanInitializedEvent event) {
log.info("Got SomeBeanInitializedEvent: {}", event);
}
}
Then register this application event listener via spring.factories or the setter method on SpringApplication/SpringApplicationBuilder:
#SpringBootApplication
public class SomeApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(SomeApplication.class)
.listeners(new SomeBeanInitializedEventApplicationListener())
.run(args);
}
...
You cannot use an #EventListener annotated method in this case because it'll be registered as a listener too late, after an event from your bean has already been fired.

How can I register a servlet with Spring Boot?

This code don't work
I have a web.xml that needs to be translated into a spring boot
<servlet>
<servlet-name>page-resolver</servlet-name>
<servlet-class>com.bk.ForwardServlet</servlet-class>
<init-param>
<param-name>page</param-name>
<param-value>/index.jsp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>page-resolver</servlet-name>
<url-pattern>/index.html</url-pattern>
<url-pattern>/login</url-pattern>
<url-pattern>/qmgr/*</url-pattern>
</servlet-mapping>
and this class
#WebServlet
public class ForwardServlet extends HttpServlet {
private String page;
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
page = config.getInitParameter("page");
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher(page).forward(req, resp);
}
}
I wrote code that registers this bean but it doesn't work and I don't understand why
#Configuration
public class ConfigureWeb implements ServletContextInitializer {
private void registerServlet(ServletContext servletContext) {
ServletRegistrationBean serviceServlet =
new ServletRegistrationBean(new ForwardServlet(), "/index.html","/login","/qmgr/*");
serviceServlet.addUrlMappings("/index.jsp");
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerServlet(servletContext);
}
}
First of all check and verify that all your resources are being kept in the correct directory.For spring-boot the jsp pages are to be kept in the directory src->main->webapp->WEB-INF->view->*.jsp .
You should have the following dependencies added in pom to compile the jsp properly when using embedded tomcat :
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- To compile JSP files -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
Now we need to tell spring where the jsp files reside, we can have two approaches for this :
Add entries in application.properties
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
Here we can specify the folder where the jsp files are to be expected, as well as define the view.
or
Configure InternalResourceViewResolver to serve JSP pages
#Configuration
#EnableWebMvc
#ComponentScan
public class MvcConfiguration extends WebMvcConfigurerAdapter
{
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
registry.viewResolver(resolver);
}
}
Now for registering servlets :
ServletRegistrationBean is used to register Servlets in Servlet 3.0 + container. We need to create a bean of ServletRegistrationBean in our JavaConfig. Find some methods of ServletRegistrationBean used to configure a Servlet.
setServlet(): Sets the servlet to be registered.
addUrlMappings(): Add URL mappings for the Servlet.
setLoadOnStartup: Sets priority to load Servlet on startup.
Suppose we have two Servlets as HelloCountryServlet and HelloStateServlet then we will register them with Spring Boot using ServletRegistrationBean as following :
#Configuration
public class WebConfig {
#Bean
public ServletRegistrationBean<HttpServlet> countryServlet() {
ServletRegistrationBean<HttpServlet> servRegBean = new ServletRegistrationBean<>();
servRegBean.setServlet(new HelloCountryServlet());
servRegBean.addUrlMappings("/country/*");
servRegBean.setLoadOnStartup(1);
return servRegBean;
}
#Bean
public ServletRegistrationBean<HttpServlet> stateServlet() {
ServletRegistrationBean<HttpServlet> servRegBean = new ServletRegistrationBean<>();
servRegBean.setServlet(new HelloStateServlet());
servRegBean.addUrlMappings("/state/*");
servRegBean.setLoadOnStartup(1);
return servRegBean;
}
}
For every Servlet we create a ServletRegistrationBean bean.
And the servlet class will look like :
public class HelloCountryServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
doGet(request,response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h3>Hello India!</h3>");
}
}
This is one approach.
Another method to register servlets in spring-boot is using annotations : #ServletComponentScan and #WebServlet. #ServletComponentScan in Spring Boot will scan Servlets annotated with #WebServlet, Filters annotated with #WebFilter and Listeners annotated with #WebListener.The annotation #ServletComponentScan is used on JavaConfig at class level. #ServletComponentScan scans Servlets, Filters and Listeners only using an embedded web server. Find the Servlets annotated with #WebServlet.
So the earlier HelloCountryServlet servlet can be provided as :
#WebServlet(urlPatterns = "/country/*", loadOnStartup = 1)
public class HelloCountryServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
doGet(request,response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h3>Hello India!</h3>");
}
}
and provide the ServletComponentScan annotation like :
#ServletComponentScan
#SpringBootApplication
public class SpringBootAppStarter {
public static void main(String[] args) {
SpringApplication.run(SpringBootAppStarter.class, args);
}
}
If you are not required to register a servlet, you could add the forwarding to the ViewControllerRegistry
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index.html").setViewName("forward:/index.jsp");
registry.addViewController("/login").setViewName("forward:/index.jsp");
registry.addViewController("/qmgr/**").setViewName("forward:/index.jsp");
}
}
You could combine the three addViewControllers into one using AntPathMatcher patterns
Map a view controller to the given URL path (or pattern) in order to
render a response with a pre-configured status code and view.
Patterns like "/admin/**" or "/articles/{articlename:\w+}" are
allowed. See AntPathMatcher for more details on the syntax.
Personally I think separating them is more readable

Failed startup of context com.google.appengine.tools.development.DevAppEngineWebAppContext

I am using Spring MVC,google app engine, admin sdk, cloud sql.
I want to access (preferncesDao) dao class into Filter.
Below is my filter
public class NameSpaceGoogleSecurityFilter implements Filter
{
#Autowired
IPreferencesDao preferncesDao;
public void init( FilterConfig filterConfig ) throws ServletException{
SpringUtils.init(filterConfig.getServletContext());
preferncesDao = SpringUtils.getPreferncesDao();
}
}
Below is my SpringUtils class.
public class SpringUtils {
private static ApplicationContext appContext;
private static IPreferencesDao preferncesDao = null;
public static void init(final ServletConfig config) {
init(config.getServletContext());
}
public static void init(final ServletContext context) {
if(appContext==null){
appContext =
(ApplicationContext) context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
}
public static IPreferencesDao getPreferncesDao() {
if(preferncesDao==null){
preferncesDao=(IPreferencesDao) appContext.getBean("preferncesDao");
}
return preferncesDao;
}
protected SpringUtils() {
throw new UnsupportedOperationException();
}
}
When I start build process, It is throwing below exception
Failed startup of context com.google.appengine.tools.development.DevAppEngineWebAppContext
java.lang.NullPointerException.
Nullpointer at line preferncesDao=(IPreferencesDao) appContext.getBean("preferncesDao");
How can i resolve above error ? is it right way to get dao object into filter ? if not what is correct way.?
It is required to add below tag in web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
That purely indicate that ContextLoaderListener missing.
so add below code in web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
For more details refer this link

Access spring component from servlet

I have a controller (for example. MyManager) where I invoke method (for example myMethod() ) of component class (bean), for example MyComponent. I have I servlet where I want to invoke myMethod() . In servlet I have annotated MyManager by #Autowired annotation , despite this I got NullPointerException. I saw this kind of topic but it is not useful for me. For imagination I write little code :
public class myClass extends HttpServlet {
#Autowired
private MyComponent component;
public void init(ServletConfig config) throws ServletException{
super.init(config);
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
protected void doGet(HttpServletRequest req,HttpServletResponse res) throws ... {
List<MyObject> objects =component.myMethod(); // Here is the problem, component is null
}
}
}
I make Spring configuration file "context.xml" and I got bean (component) object, but now I have problem with injected EntityManager in bean object. Now it is null , can anyone help me to solve this problem ? Also update init() method.
public void init(ServletConfig config) throws ServletException{
ApplicationContext con = new ClassPathXmlApplicationContext("context.xml");
component = (MyComponent) con.getBean("myBean");
}
You cannot autowire dependencies like that because Servlets are not Spring Beans. You need to do something like the following:
#Override
public void init() throws ServletException {
super.init();
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
component= applicationContext.getBean(MyComponent.class);
}
Also drop the #Autowired annotation from component

Spring inject bean into startup class during server start up

My bean is :
#Component
public class KidsServerStartUp implements ServletContextListener
{
UploadService uplService;
#Autowired
public void setUplService( UploadService uplService )
{
this.uplService = uplService;
}
public void contextInitialized(ServletContextEvent event) {
System.out.println ( uplService );
}
}
In web.xml; I am firstly calling spring framework to set all beans ; then setting the startup listener :
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.kids.util.KidsServerStartUp</listener-class>
</listener>
uplService is getting printed as null !
I think what you are looking for is something like this post.
Since you are using a ServletContextListener spring context will not be used for the creation of the Listener class. But we can get access to the ApplicationContext using the ServletContext.
public class KidsServerStartUp implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
final WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
UploadService uplService = springContext.getBean(UploadService.class);
System.out.println ( uplService );
}
}

Resources