Thread Safety in Jax-WS Request-Response Payload Logging - web-services

I am working on a SoapHandler implementation. Basically my aim is to get both request and response payloads and insert them to the database.
Although I can get the request and response payloads, I couldn't make sure if my code is working thread-safe. In other words, I am not sure if responses match with the proper requests.
public boolean handleMessage(SOAPMessageContext mContext) {
boolean isResponse = (Boolean) mContext
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (!isResponse) {
try {
mContext.put("currentStream", new ByteArrayOutputStream());
mContext.getMessage().writeTo((OutputStream) mContext.get("currentStream"));
} catch (SOAPException | IOException e) {
e.printStackTrace();
}
} else {
try {
mContext.getMessage().writeTo(
(OutputStream) mContext.get("currentStream"));
System.out.println(((OutputStream) mContext.get("currentStream"))
.toString());
((OutputStream) mContext.get("currentStream")).flush();
} catch (SOAPException | IOException e) {
e.printStackTrace();
}
}
return true;
}
I found this in JCP specs:
9.3.3 Handler Implementation Considerations
Handler instances may be pooled by a JAX-RPC runtime system. All instances of a specific handler are
considered equivalent by a JAX-RPC runtime system and any instance may be chosen to handle a particular
message. Different handler instances may be used to handle each messages of an MEP. Different threads
may be used for each handler in a handler chain, for each message in an MEP or any combination of the
two. Handlers should not rely on thread local state to share information. Handlers should instead use the
message context, see section 9.4.
9.4 Message Context
Handlers are invoked with a message context that provides methods to access and modify inbound and
outbound messages and to manage a set of properties.
Different types of handler are invoked with different types of message context. Sections 9.4.1 and 9.4.2
describe MessageContext and LogicalMessageContext respectively. In addition, JAX-RPC bindings 12
may define a message context subtype for their particular protocol binding that provides access to protocol
specific features. Section10.3 describes the message context subtype for the JAX-RPC SOAP binding.
http://download.oracle.com/otn-pub/jcp/jaxrpc-2.0-edr2-spec-oth-JSpec/jaxrpc-2_0-edr2-spec.pdf?AuthParam=1431341511_1ac4403a34d7db108bce79eda126df49
Does this imply that a new MessageContext object is created for each request (in which case I think the code will be thread safe), or the same MessageContext object can be used for multiple requests (then my code will not be thread safe).
Any help / alternative solution will be appreciated.

Rule of thumb: a FooContext object is contextual by definition, relating to a specific execution context. EJBContext relating to a single EJB; FacesContext relating to a single Faces request context; SOAPMessageContext relating to a single SOAPMessage. From the JSR-109 documentation:
The container must share the same MessageContext instance across all Handler instances and the target endpoint that are invoked during a single request and response or fault processing on a specific node.
So, you can be sure that there's one new SOAPMessageContext instance per request. Within the context of a single request however, that instance is yours to mangle. So the question really is, what do you mean by "threadsafety"? Do you plan to have multiple threads processing a single SOAPMessageContext during each request? I don't recommend it
EDIT: While the specification doesn't state in black and white that a MessageContext is threadsafe, it's implied throughout the specification. The following is an excerpt from the section of the spec that states what's possible on a MessageContext, within a handler:
Handlers may manipulate the values and scope of properties within the message context as desired. E.g. ... a handler in a server-side SOAP binding might add application scoped properties tot he message context from the contents of a header in a request SOAP message...
SOAP handlers are passed a SOAPMessageContext when invoked. SOAPMessageContext extends MessageContext with methods to obtain and modify the SOAP message payload
The specification won't be expecting programmers to modify the content of the context if it weren't safe to do so.

Related

What is the role of grpc::AuthContext, consumed_auth_metadata and response_metadata in Process()?

I've built a class that inherit grpc::AuthMetadataProcessor for assign and checking tokens for RPCs taking a cue from this question on stack-overflow and this implementation in the official GitHub repo.
A part from this block comment in auth_metadata_processor.h
/// context is read/write: it contains the properties of the channel peer and
/// it is the job of the Process method to augment it with properties derived
/// from the passed-in auth_metadata.
/// consumed_auth_metadata needs to be filled with metadata that has been
/// consumed by the processor and will be removed from the call.
/// response_metadata is the metadata that will be sent as part of the
/// response.
/// If the return value is not Status::OK, the rpc call will be aborted with
/// the error code and error message sent back to the client.
I'm having an hard time finding more resources on the use of those 3 object.
Why I need to put consumed metadata inside consumed_auth_metadata? Security purposes maybe? Convenience purposes for me, maybe?
Why I need to put metadata inside response_metadata in order to let them readable by the RPC? Doesn't they (the metadatas) pass through anyway (except path, authority and encodings metadata)?
What is the purpose of grpc::AuthContext::AddProperty() and grpc::AuthContext::SetPeerIdentityPropertyName() methods?
The only thing that I'm pretty sure I've understood is that const InputMetadata& auth_metadata contains all the metadata brought by the call like :path, :authority, encodings, user-agent and custom metadatas and some of them will not be visible inside the RPC implementation.

Using ServiceBusTrigger in the Webjobs SDK 3.x, can the Singleton attribute use a UserProperty as the scope?

I am using a ServiceBusTrigger to execute code when receiving a message. I would like to use the Singleton attribute to limit which messages can be executed in parallel. This attribute allows specifying a scope bound to properties on the incoming message, such that messages with different values can be executed in parallel but ones with the same value must be done serially.
This works when using top level properties on the incoming message object like CorrelationId.
Example
[Singleton("{CorrelationId}", SingletonScope.Function, Mode = SingletonMode.Function)]
public async Task HandleMessage(
[ServiceBusTrigger("my-topic-name", "my-subscription-name"), ServiceBusAccount("my-account-name")]
Message message,
CancellationToken cancellationToken
)
{
await Task.Yield();
}
What I am struggling to figure out is how to achieve the same behavior with user properties on the message. These are stored in the UserProperties dictionary on the Message object. I'm not seeing a way to refer to these with the binding statement in the Singleton attribute, but it seems like this would be a very common use case when combining Singleton with ServiceBusTrigger
The Service Bus Bindings exposes Message Metadata in binding expressions. So, userProperties.<key> should do the trick.

Setting JMSMessageID on stubbed jms endpoints in camel unit tests

I have a route that I am testing. I use stub://jms:queue:whatever to send/receive messages and extending CamelTestSupport for my test classes. I am having an issue with one of the routes that has a bean that uses an idempotent repo to store messages by "message id" for which it reads and stores the JMSMessageID property from exchange.
The problem I run into is that I can't figure out a way to set this property on messages sent on stubbed endpoints. Every time the method that requires this prop is called, the id returns null and i have to handle it as a null pointer. I can do this but the cleanest approach would be to just set the header on the test message. I tried includeSentJMSMessageId=true on endpoint, I tried using sendBodyAndHeader on producer and passing "JMSMessageID", "ID: whatever" in arguments, doesn't appear to work? I read that the driver/connectionfactory is supposed to set the header, but I'm not too familiar with how/where to do this. And since I am using a stubbed end points, I'm not creating any brokers/connectionfactories in my uts.
So dont stud out the JMS component replace it with a processor and then add the preferred JMSMessageID in the processor.
Something like this code:
#Test
void testIdempotency() throws Exception {
mockOut.expectedMinimumMessageCount(1);
//specify the route to test
AdviceWithRouteBuilder.adviceWith(context, "your-route-name", enrichRoute -> {
//replace the from with a end point we can call directly.
enrichRoute.replaceFromWith("direct:start");
//replace the jms endpoint with a processor so it can act as the JMS Endpoint.
enrichRoute.weaveById("jms:queue:whatever").replace().process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
//Set that ID to the one I want to test
exchange.getIn().setHeader("JMSMEssageID", "some-value-to-test");
}
});
// add an endpoint at the end to check if received a mesage
enrichRoute.weaveAddLast().to(mockOut);
});
context.start();
//send some message
Map<String,Object> sampleMsg = getSampleMessageAsHashMap("REQUEST.json");
//get the response
Map<String,Object> response = (Map<String,Object>)template.requestBody("direct:start", sampleMsg);
// you will need to check if the response is what you expected.
// Check the headers etc.
mockOut.assertIsSatisfied();
}
The JMSMessageID can only be set by the provider. It cannot be set by a client despite the fact that javax.jms.Message has setJMSMessageId(). As the JavaDoc states:
This method is for use by JMS providers only to set this field when a message is sent. This message cannot be used by clients to configure the message ID. This method is public to allow a JMS provider to set this field when sending a message whose implementation is not its own.

JXBrowser modify cookies

I have come across the https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013108-network-events in the JXBrowser and wanted to add new cookies so that it could be used in the subsequent calls.
The support is available to add headers however since no direct access is available for the cookies I tried using the
public void onBeforeSendHeaders(BeforeSendHeadersParams paramBeforeSendHeadersParams)
{
List<Cookie> cookieList = browser.getCookieStorage().getAllCookies();
}
Also note that the calls of below snippet produces the same exception
browser.getURL(); //Exception is thrown here
CookieStorage storage = setCookies(paramBeforeSendHeadersParams, browser, list);
storage.save();// Exceptino is thrown here
but if i do this i get
java.lang.IllegalStateException: You are trying to execute some code that invokes synchronous message send to IPC channel. This code is executed in the scope of the handler which is bounded to synchronous message received from IPC channel. Such code execution causes a deadlock in native code with high probability and is forbidden.
What is the reasoning behind this any help is appreciated
As I understand, you want your application to share cookies between several Browser instances.
It is possible to make Two Browser instances with the same BrowserContext instances which use the same user data directory. As a result, they will share cookies and cache files. For example:
BrowserContext context = new BrowserContext(
new BrowserContextParams("C:\\my-data1"));
Browser browser1 = new Browser(context);
Browser browser2 = new Browser(context);
In this case, you should not receive the exception.

understanding RProperty IPC communication

i'm studying this source base. Basically this is an Anim server client for Symbian 3rd edition for the purpose of grabbing input events without consuming them in a reliable way.
If you spot this line of the server, here it is basically setting the RProperty value (apparently to an increasing counter); it seems no actual processing of the input is done.
inside this client line, the client is supposed to be receiving the notification data, but it only calls Attach.
my understanding is that Attach is only required to be called once, but is not clear in the client what event is triggered every time the server sets the RProperty
How (and where) is the client supposed to access the RProperty value?
After Attaching the client will somewhere Subscribe to the property where it passes a TRequestStatus reference. The server will signal the request status property via the kernel when the asynchronous event has happened (in your case the property was changed). If your example source code is implemented in the right way, you will find an active object (AO; CActive derived class) hanging around and the iStatus of this AO will be passed to the RProperty API. In this case the RunL function of the AO will be called when the property has been changed.
It is essential in Symbian to understand the active object framework and quite few people do it actually. Unfortunately I did not find a really good description online (they are explained quite well in Symbian OS Internals book) but this page at least gives you a quick example.
Example
In the ConstructL of your CMyActive subclass of CActive:
CKeyEventsClient* iClient;
RProperty iProperty;
// ...
void CMyActive::ConstructL()
{
RProcess myProcess;
TSecureId propertyCategory = myProcess.SecureId();
// avoid interference with other properties by defining the category
// as a secure ID of your process (perhaps it's the only allowed value)
TUint propertyKey = 1; // whatever you want
iClient = CKeyEventsClient::NewL(propertyCategory, propertyKey, ...);
iClient->OpenNotificationPropertyL(&iProperty);
// ...
CActiveScheduler::Add(this);
iProperty.Subscribe(iStatus);
SetActive();
}
Your RunL will be called when the property has been changed:
void CMyActive::RunL()
{
if (iStatus.Int() != KErrCancel) User::LeaveIfError(iStatus.Int());
// forward the error to RunError
// "To ensure that the subscriber does not miss updates, it should
// re-issue a subscription request before retrieving the current value
// and acting on it." (from docs)
iProperty.Subscribe(iStatus);
TInt value; // this type is passed to RProperty::Define() in the client
TInt err = iProperty.Get(value);
if (err != KErrNotFound) User::LeaveIfError(err);
SetActive();
}