Search code examples
javaspringmavenhttpinvocation

Spring HTTP Invocation: test crashes on build server


I build an API via Spring HTTP Invocation. My config.xml looks like this:

<bean id="apiUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="/remoteapi/boat">boatEndpointExporter</prop>
        </props>
    </property>
</bean>

<bean id="boatEndpointExporter" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
    <property name="service" ref="rApiBoatEndpointImpl"/>
    <property name="serviceInterface" value="xxx.RApiBoatEndpoint"/>
</bean>

This is my test case: It pretends to call the API from outside the application and trys to ping it.

  @Test
public void invokePing() {
    RApiBoatEndpoint remoteInteface = buildRemoteInteface();
    assertEquals("test", remoteInteface.ping("test"));
}

private RApiBoatEndpoint buildRemoteInteface() {

    String url = WebDriverResourceManager.BASE_URL + "/remoteapi/boat";
    System.out.println("build remote interface for RApiBoatEndpoint - url=" + url);

    PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
    poolingHttpClientConnectionManager.setMaxTotal(100);
    poolingHttpClientConnectionManager.setDefaultMaxPerRoute(5);

    CloseableHttpClient httpClient = HttpClientBuilder.create()
            .setConnectionManager(poolingHttpClientConnectionManager)
            .build();

    HttpComponentsHttpInvokerRequestExecutor httpComponentsHttpInvokerRequestExecutor = new HttpComponentsHttpInvokerRequestExecutor();
    httpComponentsHttpInvokerRequestExecutor.setHttpClient(httpClient);

    HttpInvokerProxyFactoryBean factory = new HttpInvokerProxyFactoryBean();
    factory.setServiceUrl(url);
    factory.setServiceInterface(RApiBoatEndpoint.class);
    factory.setHttpInvokerRequestExecutor(httpComponentsHttpInvokerRequestExecutor);
    factory.afterPropertiesSet();
    return (RApiBoatEndpoint) factory.getObject();
}

The test passes both locally in my IDE and via maven. I can call the api manually and from the client application.

But our build server keeps saying that it doesn't work:

org.springframework.remoting.RemoteAccessException: Could not access HTTP invoker remote service at [http://xxxx/remoteapi/boat]; nested exception is org.apache.http.NoHttpResponseException: Did not receive successful HTTP response: status code = 404, status message = [Not Found]
at org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor.validateResponse(HttpComponentsHttpInvokerRequestExecutor.java:233)
at org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor.doExecuteRequest(HttpComponentsHttpInvokerRequestExecutor.java:149)
at org.springframework.remoting.httpinvoker.AbstractHttpInvokerRequestExecutor.executeRequest(AbstractHttpInvokerRequestExecutor.java:138)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:194)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:176)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:144)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy36.ping(Unknown Source)

Any suggestions how to fix the problem?


Solution

  • After some days of tedious bug seeking we find a solution: Our build server loads files in another order than local maven, for that reason we could never reproduce the bug locally.

    Our config-file included this:

    <mvc:default-servlet-handler/>
    

    Our build server loaded this config-file first, later the api-config-file.

    Solution was to let our SimpleUrlHandler be registered at first by giving it a very low order:

    <bean id="apiUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="order" value="-1" />
        <property name="mappings">
            <props>
                <prop key="/remoteapi/boat">boatEndpointExporter</prop>
            </props>
        </property>
    </bean>