0

I hava a project on Wildfly 8. So in it i have 1 war application, and many sar applications. In war i have controllers for managing entities, which are disposed in sar. mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd" default-lazy-init="true">
    <context:component-scan base-package="com.a1s.assist.web"/>
    <mvc:annotation-driven/>

</beans>

web.xml

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/mvc/*</url-pattern>
</servlet-mapping>

<context-param>
    <param-name>parentContextKey</param-name>
    <param-value>assist.context</param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>


<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

My servlet code:

package com.a1s.assist.web.broadcast.controller;

/**
 * @author Alexey Belov
 */

import com.a1s.assist.broadcast.manager.BroadcastZoneManager;
import com.a1s.assist.broadcast.obj.BroadcastZone;
import com.a1s.assist.web.settings.controller.BaseSpringController;
import com.a1s.assist.web.settings.util.Messages;
import com.a1s.util.misc.ExceptionUtil;
import com.a1s.web.action.BaseAction;
import com.a1s.web.controller.FrontJsonController;
import org.jboss.logging.Logger;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@Lazy
@Controller
@RequestMapping(method = {RequestMethod.POST}, value = "/broadcast/zone")
public class BroadcastZoneController extends BaseSpringController {


    private Logger log = Logger.getLogger(BroadcastZoneController.class);
    @Autowired
    private BroadcastZoneManager broadcastZoneManager;

    @ResponseBody
    @RequestMapping(value = "/list")
    public void list(HttpServletRequest request,
                     HttpServletResponse response
    ) throws IOException {
        final ServletOutputStream out = response.getOutputStream();
        try {
            log.info("list zones");
            final JSONObject requestJson = (JSONObject) request.getAttribute(FrontJsonController.REQUEST_JSON_PARAMETER);
            final JSONObject parseJson = requestJson.getJSONObject("request").getJSONObject("params").getJSONObject(BroadcastZone.WRAP);
            final String operatorId = parseJson.getString("operatorId");
            final String parentId = parseJson.getString("parentId");
            final List<BroadcastZone> all = broadcastZoneManager.listChildsTree(parentId, operatorId);
            final List list = BaseAction.toJson(all);
            BaseAction.sendJsonOk(out, list);
        } catch (Exception e) {
            log.error(e);
            BaseAction.sendJsonError(out, Messages.IO_ERROR, "Unknown error: " + ExceptionUtil.getStackTrace(e), new JSONObject());
        }
    }
}

So when i try to start wildfly without module which contains BroadcastZone, i get exception:

Failed to start service jboss.undertow.deployment.default-server.default-host./ROOT: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./ROOT: Failed to start service
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_05]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_05]
        at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_05]
Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: com/a1s/assist/broadcast/obj/BroadcastZone
        at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:222)
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:87)
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.start(UndertowDeploymentService.java:72)
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
        ... 3 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: com/a1s/assist/broadcast/obj/BroadcastZone
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
        at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
        at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:173)
        at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:193)
        ... 7 more
Caused by: java.lang.NoClassDefFoundError: com/a1s/assist/broadcast/obj/BroadcastZone
        at java.lang.Class.getDeclaredMethods0(Native Method) [rt.jar:1.8.0_05]
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2688) [rt.jar:1.8.0_05]
        at java.lang.Class.getDeclaredMethods(Class.java:1962) [rt.jar:1.8.0_05]
        at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:571)
        at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:488)
        at org.springframework.web.method.HandlerMethodSelector.selectMethods(HandlerMethodSelector.java:57)
        at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:169)
        at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:144)
        at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:123)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:126)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
        ... 21 more
Caused by: java.lang.ClassNotFoundException: com.a1s.assist.broadcast.obj.BroadcastZone from [Module "deployment.ROOT.war:main" from Service Module Loader]
        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:213)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:459)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:408)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:389)
        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:134)
        ... 33 more

What can i do to make spring load controllers only when request is posting on my mapping. And NoClassDefFound error should raise only then, but not during startup?

Danielson
  • 2,605
  • 2
  • 28
  • 51
Alex Belov
  • 111
  • 4
  • This guy : com/a1s/assist/broadcast/obj/BroadcastTemplate is not properly autowired/connected/instantiated by/to Spring. – We are Borg Jul 06 '15 at 14:48
  • If the above file is not from your project, then you are missing some dependency. – We are Borg Jul 06 '15 at 14:48
  • I want this guy to be missing from project, i want RequestMappingHandlerMapping to load this class only when a request to /zone/list will be performed – Alex Belov Jul 06 '15 at 15:10
  • Just tell me if it is a dependency? I cannot suggest u alternatives for not using a maven dependency..but what i can do is to help u sort when u identify missing dependency. – We are Borg Jul 06 '15 at 17:00
  • Now I get it, its a class you have.... It is not autowired properly. Can you tell me what BroadcastZone does, and paste the code by editing your main post. – We are Borg Jul 06 '15 at 18:40
  • BroadcastZone is just a POJO. But i want my web app to have an OPTIONAL dependency on it. My project have a module architecture, so module "broadcast", which contain class BroadcastZone can be installed and can be uninstalled, it is made by application serverd (deployed and undeployed app). So i want spring-mvc to search this class in classpath only when request is processing (POST on /zone/list). BroadcastZone must not be searched during application startup. – Alex Belov Jul 07 '15 at 07:21
  • Why don't you create a JAR out of it, put it in your classpath, and set the scope to runtime. – We are Borg Jul 07 '15 at 08:23

1 Answers1

0

I finally realized why that error happenned. The thing is in load-on-startup element. I thought it will not load on startup when the value is zero. Today i figured out, that:

The load-on-startup element indicates that this servlet should be loaded (instantiated and have its init() called) on the startup of the web application. The optional contents of these element must be an integer indicating the order in which the servlet should be loaded. If the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses. If the value is a positive integer or 0, the container must load and initialize the servlet as the application is deployed. The container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-start-up value.

That is why i got NoClassDefFound on startup.

Alex Belov
  • 111
  • 4