0

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?

Shareil
  • 69
  • 1
  • 6
  • I think this is the case wher `xxxx` in your exception is actually important. Is that `localhost`? If no, what is that and what happens when you open that URL in the browser? Is it really HTTP 404? Is there really any server at that URL when your tests are run? – SergGr Mar 16 '17 at 17:38
  • @SergGr xxx Is the name of the respective buildnode, something like this: http://hudsonjava05.xxx.org:8418/xxxxx/remoteapi/boat. it is configured in each build nodes' context.xml. Tests are run via maven, which starts cargo. There are some other tests (in same package) which also require a running server, these tests pass. So I think it is no general problem but something about my test setup/config. – Shareil Mar 17 '17 at 07:12
  • Normally I can't call the url because this server only runs for the (selenium) tests. But I will try to call it next time server is building... Maybe I will find something enlightning. – Shareil Mar 17 '17 at 07:19
  • @SergGr noticed something strange: http_response.log says this: POST:/xxx/remoteapi/boat status:200, but access_log says this: (via org.apache.catalina.valves.AccessLogValve) ""POST /xxx/remoteapi/boat HTTP/1.1" 404" – Shareil Mar 17 '17 at 09:57

1 Answers1

0

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>
Shareil
  • 69
  • 1
  • 6