[neon] How to pass per-request information from client to server? [message #1753536] |
Tue, 07 February 2017 10:05  |
Eclipse User |
|
|
|
In the Mars version of our application we created a "request-id" for each server call that we passed to the server. This request id was then used in all log statements, so that we can reconcile logs in the client and server logs.
The way we did this was that we extended the ServiceTunnelRequest, the ClientHttpServiceTunnel and the ServiceTunnelServlet with implementations of our own.
We then overrode ClientHttpServiceTunnel.decorateBackgroundJob() in which we set the requestId property of our own ServiceTunnelRequest implementation. In ServiceTunnelServlet.runServerJobTransaction() and ServiceTunnelServlet.runServerJobTransactionWithDelegate() we then extracted this information and stored it on a per-thread context.
However, as the whole service tunnel mechanism was greatly refactored in Neon we had to throw all this out at the very start. Unfortunately we didn't realise this would break our log-request-id mechanism.
What is the recommended way to pass per-service-call information from client to server implicitely in Neon?
[Updated on: Tue, 07 February 2017 10:11] by Moderator
|
|
|
|
|
|
Re: [neon] How to pass per-request information from client to server? [message #1753608 is a reply to message #1753543] |
Wed, 08 February 2017 02:54   |
Eclipse User |
|
|
|
Arthur
It seems that addCustomHeader is what I need. However, I have trouble getting this to work. I've tried the following:
@Replace
public class MyHttpServiceTunnel extends HttpServiceTunnel {
public final static String HEADER_REQUEST_ID = "MyRequestId";
@Override
protected void addCustomHeaders(URLConnection urlConn, String method, byte[] callData) throws IOException {
super.addCustomHeaders(urlConn, method, callData);
addRequestId(urlConn);
}
protected void addRequestId(final URLConnection urlConn) throws IOException {
String reqid = RequestIdUtil.getNewRequestId();
urlConn.setRequestProperty(HEADER_REQUEST_ID, reqid);
}
}
I thought adding the @Replace annotation would be sufficient to ensure that my service tunnel implementation would be used but when starting the ui-server I get the exception listed at the end of my post.
Also, I've tried finding the code location where the correlation id is retrieved on server side but have not been succesful so far. Can you give me a hint?
[2017-02-08 08:52:30,622] [Thread-3] ERROR org.eclipse.scout.rt.platform.internal.PlatformImplementor start - Error during platform startup
org.eclipse.scout.rt.platform.exception.BeanCreationException: Could not create bean [org.eclipse.scout.rt.client.clientnotification.ClientNotificationPoller]
at org.eclipse.scout.rt.platform.internal.BeanInstanceUtil.translateException(BeanInstanceUtil.java:89)
at org.eclipse.scout.rt.platform.internal.BeanInstanceUtil.createAndInitializeBean(BeanInstanceUtil.java:52)
at org.eclipse.scout.rt.platform.internal.DefaultBeanInstanceProducer.createInstance(DefaultBeanInstanceProducer.java:101)
at org.eclipse.scout.rt.platform.internal.DefaultBeanInstanceProducer.safeCreateInstance(DefaultBeanInstanceProducer.java:83)
at org.eclipse.scout.rt.platform.internal.DefaultBeanInstanceProducer.access$0(DefaultBeanInstanceProducer.java:71)
at org.eclipse.scout.rt.platform.internal.DefaultBeanInstanceProducer$1.call(DefaultBeanInstanceProducer.java:60)
at org.eclipse.scout.rt.platform.util.FinalValue.setIfAbsent(FinalValue.java:90)
at org.eclipse.scout.rt.platform.internal.DefaultBeanInstanceProducer.getApplicationScopedInstance(DefaultBeanInstanceProducer.java:57)
at org.eclipse.scout.rt.platform.internal.DefaultBeanInstanceProducer.produce(DefaultBeanInstanceProducer.java:34)
at org.eclipse.scout.rt.platform.internal.BeanImplementor.getInstance(BeanImplementor.java:72)
at org.eclipse.scout.rt.platform.internal.BeanManagerImplementor.startCreateImmediatelyBeans(BeanManagerImplementor.java:245)
at org.eclipse.scout.rt.platform.internal.PlatformImplementor.startCreateImmediatelyBeans(PlatformImplementor.java:236)
at org.eclipse.scout.rt.platform.internal.PlatformImplementor.start(PlatformImplementor.java:137)
at org.eclipse.scout.rt.platform.internal.PlatformStarter.run(PlatformStarter.java:32)
Caused by: org.eclipse.scout.rt.platform.exception.BeanCreationException: Exception while invoking @PostConstruct method
at org.eclipse.scout.rt.platform.internal.BeanInstanceUtil.translateException(BeanInstanceUtil.java:89)
at org.eclipse.scout.rt.platform.internal.BeanInstanceUtil.initializeBeanInstance(BeanInstanceUtil.java:69)
at org.eclipse.scout.rt.platform.internal.BeanInstanceUtil.createAndInitializeBean(BeanInstanceUtil.java:49)
... 12 more
Caused by: org.eclipse.scout.rt.platform.util.Assertions$AssertionException: Assertion error: multiple instances found for query: interface org.eclipse.scout.rt.shared.servicetunnel.IServiceTunnel [IBean[@Replace @Bean core.scout.shared.servicetunnel.MyHttpServiceTunnel], IBean[@Replace @Bean org.eclipse.scout.rt.client.servicetunnel.http.ClientHttpServiceTunnel]]
at org.eclipse.scout.rt.platform.util.Assertions.fail(Assertions.java:580)
at org.eclipse.scout.rt.platform.internal.BeanManagerImplementor.optBean(BeanManagerImplementor.java:222)
at org.eclipse.scout.rt.platform.BEANS.opt(BEANS.java:55)
at org.eclipse.scout.rt.platform.BEANS.get(BEANS.java:41)
at org.eclipse.scout.rt.client.clientnotification.ClientNotificationPoller.start(ClientNotificationPoller.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.eclipse.scout.rt.platform.internal.BeanInstanceUtil.initializeBeanInstance(BeanInstanceUtil.java:66)
... 13 more
[Updated on: Wed, 08 February 2017 02:56] by Moderator
|
|
|
|
|
Re: [neon] How to pass per-request information from client to server? [message #1753615 is a reply to message #1753612] |
Wed, 08 February 2017 03:33   |
Eclipse User |
|
|
|
Arthur
Thanks, with a low @Order everything works nicely now. The additional code is actually a lot simpler than the corresponding Scout-Mars code:
On client side:
@Replace
public class MyClientHttpServiceTunnel extends ClientHttpServiceTunnel {
public final static String HEADER_REQUEST_ID = "MyRequestId";
@Override
protected void addCustomHeaders(URLConnection urlConn, String method, byte[] callData) throws IOException {
super.addCustomHeaders(urlConn, method, callData);
addRequestId(urlConn);
}
protected void addRequestId(final URLConnection urlConn) throws IOException {
String reqid = RequestIdUtil.getNewRequestId();
urlConn.setRequestProperty(HEADER_REQUEST_ID, reqid);
}
}
And on server side:
public class CisServiceTunnelServlet extends ServiceTunnelServlet {
private static final long serialVersionUID = 1L;
@Override
protected ServletRunContext createServletRunContext(final HttpServletRequest req, final HttpServletResponse resp) {
final String reqid = req.getHeader(CisHttpServiceTunnel.HEADER_REQUEST_ID);
LogContextUtil.putRequestContext(reqid != null ? reqid.toString() : null);
return super.createServletRunContext(req, resp);
}
}
And then in the web.xml:
<!-- <servlet-class>org.eclipse.scout.rt.server.ServiceTunnelServlet</servlet-class> -->
<servlet-class>ch.sbb.cisi.core.scout.server.CisServiceTunnelServlet</servlet-class>
Overwriting the CorrelationId might work (we need a numeric value instead of a UUID) but would only save me the code on the client side as I still would need to extract the correlation-id and pass it to our LogContextUtil as we are using a spring backend outside the scout code scope.
Thanks for your help!
[Updated on: Wed, 08 February 2017 05:39] by Moderator
|
|
|
|
Re: [neon] How to pass per-request information from client to server? [message #1753632 is a reply to message #1753625] |
Wed, 08 February 2017 05:35  |
Eclipse User |
|
|
|
Hi Jeremy
You are right, that was exactly the problem. While @Order helped to only instantiate my class, it actually broke scout because it now replaced ClientHttpServiceTunnel which destroyed the syncrhonisation of the server and client sessions. When I changed my class to extend ClientHttpServiceTunnel that worked again. I guess replacing the @Order annotation with @Replace will be sufficient again.
I've adjusted the code above to represent the correct solution.
Thanks for your help.
|
|
|
Powered by
FUDForum. Page generated in 0.04676 seconds