[neon] How to pass per-request information from client to server? [message #1753536] |
Tue, 07 February 2017 15:05 |
Urs Beeli Messages: 573 Registered: October 2012 Location: Bern, Switzerland |
Senior Member |
|
|
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 15:11] Report message to a 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 07:54 |
Urs Beeli Messages: 573 Registered: October 2012 Location: Bern, Switzerland |
Senior Member |
|
|
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 07:56] Report message to a moderator
|
|
|
|
Re: [neon] How to pass per-request information from client to server? [message #1753612 is a reply to message #1753608] |
Wed, 08 February 2017 08:18 |
Arthur van Dorp Messages: 48 Registered: October 2015 |
Member |
|
|
For services you have to use the @Order annotation (lower number wins).
On the server side the ServiceTunnelServlet.createServletRunContext retrieves the correlation id from the http headers if present or creates a new one and adds it to the ServletRunContext.
Edit: Just seen your last update: Yes, that should do it. I still believe that you are copying and extending a lot of code for dubious profit. If you need the correlation id to be something else than the current UUID you could try to overwrite simply the CorrelationId bean with a new implementation of newCorrelationId(). (I have never tried that).
[Updated on: Wed, 08 February 2017 08:24] Report message to a 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 08:33 |
Urs Beeli Messages: 573 Registered: October 2012 Location: Bern, Switzerland |
Senior Member |
|
|
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 10:39] Report message to a moderator
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.05099 seconds