Spring HTTP 调用:构建服务器上的测试崩溃
Spring HTTP Invocation: test crashes on build server
我通过 Spring HTTP 调用构建了一个 API。我的 config.xml 看起来像这样:
<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>
这是我的测试用例:
它假装从应用程序外部调用 API 并尝试 ping 它。
@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();
}
测试在我的 IDE 本地和通过 maven 都通过了。
我可以手动和从客户端应用程序调用 api。
但是我们的构建服务器一直说它不起作用:
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)
有什么解决问题的建议吗?
经过几天乏味的 bug 查找,我们找到了解决方案:
我们的构建服务器以不同于本地 Maven 的顺序加载文件,因此我们永远无法在本地重现该错误。
我们的配置文件包括:
<mvc:default-servlet-handler/>
我们的构建服务器首先加载了这个配置文件,然后是 api-config 文件。
解决方案是让我们的 SimpleUrlHandler 首先注册,方法是给它一个非常低的顺序:
<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>
我通过 Spring HTTP 调用构建了一个 API。我的 config.xml 看起来像这样:
<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>
这是我的测试用例: 它假装从应用程序外部调用 API 并尝试 ping 它。
@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();
}
测试在我的 IDE 本地和通过 maven 都通过了。 我可以手动和从客户端应用程序调用 api。
但是我们的构建服务器一直说它不起作用:
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)
有什么解决问题的建议吗?
经过几天乏味的 bug 查找,我们找到了解决方案: 我们的构建服务器以不同于本地 Maven 的顺序加载文件,因此我们永远无法在本地重现该错误。
我们的配置文件包括:
<mvc:default-servlet-handler/>
我们的构建服务器首先加载了这个配置文件,然后是 api-config 文件。
解决方案是让我们的 SimpleUrlHandler 首先注册,方法是给它一个非常低的顺序:
<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>