1

Situation: I have a local environment and I deploy the web app to a vanilla tomcat server. Application runs as intended. I deploy to Azure and I get a NPE during deployment. The Azure tomcat server is suppose to be vanilla as well.

Question The question is why would I get an NPE in one environment preventing the app from running and not get the same NPE in a different environment when both environment as suppose to be the same? Where would I start looking?

Or to put it another way: "Why does container.addServlet("dispatcher", new DispatcherServlet(ctx)) return null 'if this ServletContext already contains a complete ServletRegistration for the given servletName' on production? When it is not doing it in my local/dev environment.

New to java, new to azure, and hip deep in trouble. Using eclipse with the azure toolkit plugin.

Web app runs on local tomcat server just fine. Talks to the mysql db deployed on azure just fine.

I attempted to deploy to azure. It says that it published correctly but I am receiving 404 errors. Can't figure out how to get logging to work correctly on azure but was able to get the stream working. After copying the stream and spending a lot of time formatting the output here is the only error that occurs when deploying:

07-Feb-2020 05:57:32.426 SEVERE [main] org.apache.catalina.startup.HostConfig.deployDirectory Error deploying web application directory [D:\home\site\wwwroot\webapps\hds]java.lang.IllegalStateException: Error starting child
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:716)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1133)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1868)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
    at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:1045)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:429)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1577)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:309)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
    at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:424)
    at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:367)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:934)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1382)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1372)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:907)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:933)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:637)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492)Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/hds]]
    at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:441)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713)... 37 moreCaused by: java.lang.NullPointerException
    at hds.configs.ApplicationInitializer.onStartup(ApplicationInitializer.java:21)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5120)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)... 38 more

the interesting part seems to be:

at hds.configs.ApplicationInitializer.onStartup(ApplicationInitializer.java:21)

Here is the "offending" code:

public class ApplicationInitializer implements WebApplicationInitializer {

            public void onStartup(ServletContext container) throws ServletException {

                AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
                ctx.register(WebMvcConfig.class);
                ctx.setServletContext(container);

                ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx));

                //servlet.setLoadOnStartup(1);
                servlet.setLoadOnStartup(-1);
                servlet.addMapping("/");
            }
}

Line 21 of the code is: ''' servlet.setLoadOnStartup(-1); '''

and if you need the WebMvcConfig.class:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "hds.controllers,hds.daos,hds.services,hds.configs")
public class WebMvcConfig implements WebMvcConfigurer {
     @Bean
       public InternalResourceViewResolver resolver() {
          InternalResourceViewResolver resolver = new InternalResourceViewResolver();
          resolver.setViewClass(JstlView.class);
          resolver.setPrefix("/WEB-INF/views/");
          resolver.setSuffix(".jsp");
          return resolver;
       }


     @Bean
       public MessageSource messageSource() {
          ResourceBundleMessageSource source = new ResourceBundleMessageSource();
          source.setBasename("messages");
          return source;
       }

     @Override
       public Validator getValidator() {
          LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
          validator.setValidationMessageSource(messageSource());
          return validator;
       }
}

I have no idea why this would generate this error. Like I said before I am very new to java and azure and with full disclosure this is part of a college capstone project. creating a website instead of a cms and tying it to database is bonus.

If someone could tell me how to get the logs running on azure, that would be helpful. I went ahead and got a storage account and turned the logs on but I have no idea how to access them.

I tried using azure support and while the gentleman was nice but he was clearly out of his depth.

Like I said runs locally just fine and the configs are pretty much boiler plate (I think based on my research).

SecretAgentMan
  • 2,856
  • 7
  • 21
  • 41
Chris
  • 21
  • 2
  • If it was truly a Null pointer issue wouldn't the problem present itself in the local deployment? Please open my question back up. – Chris Feb 07 '20 at 07:25
  • So your app runs fine on local Tomcat and fails with NPE on Azure Tomcat? – Suncatcher Feb 07 '20 at 09:30
  • Make sure you are using the **exact** same Java and Tomcat version locally as on azure. Also don't set the `ServletContext` as the `DispatcherServlet` will take care of that. Finally add a log configuration to enable trace/debug logging to see what is going on. – M. Deinum Feb 07 '20 at 10:27
  • @Deinum not really sure how to do to create the servlet without setting it that way. Every example I have found uses that method. I turned on Insights, added log4j, and the maven depends to connect the two. I have no experience with either but will read and try to put something together. – Chris Feb 07 '20 at 13:32
  • We have success. I ended up reading this deployment example:https://howtodoinjava.com/spring5/webmvc/spring5-mvc-hibernate5-example/ and used their AppInitializer class and it seems to have published and is operational. Now I just need to research why this class worked and the other one didn't. – Chris Feb 07 '20 at 16:34

2 Answers2

0

In Azure App Service you can choose between different versions of Tomcat, please make sure you are targeting the same version you are testing with.

If you still hit issue, please create an Azure support request and we will assist: https://learn.microsoft.com/en-us/azure/azure-portal/supportability/how-to-create-azure-support-request

Joaquín Vano
  • 414
  • 1
  • 3
  • 5
-1

In the following link you will find how to enable logs for your Web App on App Service and how to stream them using the portal or CLI: https://learn.microsoft.com/en-us/azure/app-service/troubleshoot-diagnostic-logs

You can download the Logs using FTP: https://learn.microsoft.com/en-us/azure/app-service/deploy-ftp#get-ftp-connection-information

The logs should be in the /site/LogFiles folder.

Joaquín Vano
  • 414
  • 1
  • 3
  • 5