Announcement Announcement Module
Collapse
No announcement yet.
Running Jetty from Junit under Maven...differing behaviour on server Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Running Jetty from Junit under Maven...differing behaviour on server

    I am running a jetty-servlet-tester from a unit test; it stands up a spring servlet, which I then query in the rest of the tests. It works fine from my IDE, and from maven on my desktop's command line. However, when I try to run it using maven on the build server, it is suddenly unable to resolve the urls I'm sending it. Why would the SimpleUrlHandlerMapping behave differently on a different machine? The maven version is identical; the only environmental difference I see is the JRE version (my machine has 1.6.24, the server has 1.6.10).

    In reverse order, the error message:

    Code:
    08/18/2011 18:39:53 WARN servlet.DispatcherServlet No mapping found for HTTP request with URI [/api/copyfile/to/1/artifact/source] in DispatcherServlet with name 'testApiServlet'
    ...the actual application context of the spring webapp (applicationContext-internalapi.xml):

    Code:
    <beans>
        ...
    
        <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
                <value>
                    /job/**=apiJobController
                    /copyfile/**=apiCopyFileController
                    /parsefile/**=apiParseFileController
                </value>
            </property>
        </bean>
        ...
    </bean>
    ...the testApiServlet.xml, which the Jetty fired spring servlet looks for (I had no luck attaching a ContextLoaderListener with the real webapp's config):

    Code:
    <beans>
        <import resource="classpath*:applicationContext-internalapi.xml" />
    </beans>
    ...and the Jetty setup:

    Code:
        private ServletTester tester;
        private String baseUrl;
        private final File currentDir = new File(System.getProperty("user.dir"));
    
        @Before
        public void setup() throws Exception {
            // copy WEB-INF to the current dir so that when running from maven, we can find this
            final PathMatchingResourcePatternResolver pmrpr = new PathMatchingResourcePatternResolver();
            final File file = pmrpr.getResource("classpath:WEB-INF/testApiServlet-servlet.xml").getFile();
            final File webinf = file.getParentFile();
            org.apache.commons.io.FileUtils.copyDirectoryToDirectory(webinf, currentDir);
    
            tester = new ServletTester();
            tester.setContextPath("/api");
            final ServletContextHandler context =  tester.getContext();
            final ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class);
            servletHolder.setName("testApiServlet");
            context.addServlet(servletHolder, "/*");
            context.setResourceBase(currentDir.getAbsolutePath());
            baseUrl = tester.createSocketConnector(true);
            client.setBaseUrl(baseUrl + "/api");
            tester.start();
            ...
    I don't really love the WEB-INF copying (or the lack of the ContextLoaderListener), but again, this works both from the IDE and from maven on my desktop's terminal.

  • #2
    Well, I at least understand what's going on now, although don't yet have a fix. The * in

    <beans>
    <import resource="classpath*:applicationContext-internalapi.xml" />
    </beans>

    ...apparently tells the import not to complain if it can't find the resource. I modified the name to applicatiosdsdfsdfsdfsdfContext-internalapi.xml, and the context initialization didn't complain (it does w/o the *). A nasty gotcha!

    Anyway, it seems that this might be a classloader issue. I'll try to workaround via altering my Jetty config, and remove the WEB-INF hack. Does anybody know how to make the ContextLoaderListener work with a setup like this?
    Last edited by reuben; Aug 18th, 2011, 08:19 PM.

    Comment


    • #3
      The problem stems from Jetty's need to have a resourceBase, which makes it hard to configure it so that it runs both under Maven and an IDE. I made the following changes:

      Code:
          @Before
          public void setup() throws Exception {
              tester = new ServletTester();
              tester.setContextPath("/api");
              final ServletContextHandler context =  tester.getContext();
              final ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class);
              servletHolder.setName("testApiServlet");
              context.addServlet(servletHolder, "/*");
      
              // work out if we're in an IDE or maven
              final File target = new File("projectname");
              if (target.exists()) {
                  // IDE
                  context.setResourceBase("projectname/src/main/webapp");
              } else {
                  // maven
                  context.setResourceBase("src/main/webapp");
              }
              baseUrl = tester.createSocketConnector(true);
              client.setBaseUrl(baseUrl + "/api");
              tester.start();
          }
      ... and ...

      Code:
      <beans>
          <import resource="classpath:applicationContext-internalapi.xml" />
      </beans>
      It's hacky, and there's got to be a better way to hook Jetty up. But it works.

      Comment


      • #4
        Did you find a nicer way to do this?

        Comment

        Working...
        X