Undertow's ThreadSetupAction: null exchange - wildfly

I'm using Wildfly 8.1.0.Final, which has Undertow 1.0.15.Final bundled.
I have a certain ThreadSetupAction implementation, that gets called with a null exchange sporadically. I'm not sure how to correctly handle this case.
ThreadSetupAction's javadoc says:
Interface that can be implemented by classes that need to setup and thread local context before a request is processed.
ThreadSetupAction#setup's javadoc mentions:
Parameters:
exchange The exchange, this may be null
So what does it mean, when the exchange is null? How can there be a request without an exchange?
So far I was unable to catch this with a debugger.

ThreadSetupAction#setup gets called with a null exchange in the following cases.
Deployment events: deploy, undeploy, start, stop.
Servlets' AsyncContext.start.
Servlets' sessionDestroyed event.

Related

Smack throws NullPointerException in Roster's presence listener

I'm using Smack with android chatting applications and recently I have updated Smack to version to 4.3.0 and getting some error in fabric. It is a NullPointerException inside of Smack:
Fatal Exception: java.lang.NullPointerException
Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference
java.util.concurrent.ConcurrentHashMap.get (ConcurrentHashMap.java:772)
org.jivesoftware.smack.roster.Roster.getPresencesInternal (Roster.java:374)
org.jivesoftware.smack.roster.Roster.getOrCreatePresencesInternal (Roster.java:388)
org.jivesoftware.smack.roster.Roster.access$1100 (Roster.java:94)
org.jivesoftware.smack.roster.Roster$PresencePacketListener$1.run (Roster.java:1502)
org.jivesoftware.smack.AsyncButOrdered$Handler.run (AsyncButOrdered.java:121)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1113)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:588)
java.lang.Thread.run (Thread.java:818)
"Use the source, Luke (and study the relevant open standard)" Obi-Wan Kenobi
Smack is open soure, so let us look at the source: One interesting part is
org.jivesoftware.smack.roster.Roster.getPresencesInternal (Roster.java:374)
which reads
Map<Resourcepart, Presence> entityPresences = presenceMap.get(entity);
Source: https://github.com/igniterealtime/Smack/blob/4.3.0/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java#L374
We also find that presenceMap is declared as follows
private final Map<BareJid, Map<Resourcepart, Presence>> presenceMap = new ConcurrentHashMap<>();
Source: https://github.com/igniterealtime/Smack/blob/4.3.0/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java#L168
So it is a ConcurrentHashMap, which matches with the stacktrace. It is obvous that entity above is null, which is the cause of the NullPointerException.
Now we need to walk the call stack up (or down, depening on your point of view), to determine where entity origins from. Here the interesting part is
org.jivesoftware.smack.roster.Roster$PresencePacketListener$1.run (Roster.java:1502)
which reads
userPresences = getOrCreatePresencesInternal(key);
Source: https://github.com/igniterealtime/Smack/blob/4.3.0/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java#L1562
so enitty is key here. Which is declare and define just a few lines above
final BareJid key = from != null ? from.asBareJid() : null;
Source: https://github.com/igniterealtime/Smack/blob/4.3.0/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java#L1562
So in case from is null, keywill also be null. Which later causes theNullPointerException. Looking at the code, we find that this is caused by a presence XMPP stanza without a from` attribute set.
The question is now if those stanzas are legal in XMPP. To determine that, we need to have a look at the specification. The relevant part is [RFC 6120 ยง 8.1.2.1 4.],1, which states
When the server generates a stanza from the server for delivery
to the client on behalf of the account of the connected client
(e.g., in the context of data storage services provided by the
server on behalf of the client), the stanza MUST either (a) not
include a 'from' attribute or (b) include a 'from' attribute
whose value is the account's bare JID (localpart#domainpart).
So a missing 'from' attribute is generally allowed and is equal to the "account's bare JID".
Now the question is: Are there any presence stanzas specified send from the server to the client which do not have a 'from' attribute? I could not find any while reading the related RFC 6121. And I am not aware when this should ever happen (I possibly could be missing someting). But right now this appears to be a bug in the entity which creates those presence stanzas, which is the used XMPP server implementation.
(What XMPP server implementation do you use?).

How can i append the username (principal) to each log line in Wildfly?

I am working with Wildfly 10 and I am using its logging subsystem.
Now, I need to append the LoginName of the currently logged in User (principal) from the session to every log message that is processed by the JBoss Logging Subsystem.
Is there a generic way to do this, rather than appending the UserName to every Log Message in my Application?
For example i could do:
HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
UserModel user = (UserModel)request.getSession().getAttribute("user");
String username = user.getName();
But how can i get the Logging Subsystem to do this for every Log Message?
As James R. Perkins suggested, this can be done be using MDC (Mapped Diagnostic Context).
An example of how this works can be found here:
https://veerasundar.com/blog/2009/11/log4j-mdc-mapped-diagnostic-context-example-code/
I encountered the same situation as yours and found that there is no Wildfly in built support for the same.
Hence the two options that you can have are-
Append username to the logs manually as what you mentioned already in your question. Personally I prefer this to keep the logging minimum and relevant.
Use MDC and along with that implement 'filter' attribute of logging in Wildfly, so that you can keep only relevant log messages in your log file.

How do I send a Diameter message to an IP other than Destination-Host's value in mobicents

In all Diameter implementations I saw, the messages originating from the server is always sent towards the DNS resolved IP address of whats in the Destination-Host AVP. But, in commercial servers, we see an option to configure a DRA or a DEA which takes in all the messages and routes them.
Thus, when it comes to the mobicents diameter stack, this approach is sometimes hard to do. I can anyway re-configure the hosts file so that the message ends up in a DRA/DEA, yet, its a pain. I see no option to send these messages to a central diameter agent which will take care of all the dirty work for me.
The next issue is, if I plan to create such a DRA/DEA, the stack does not accept messages to a different host. Where, the message's Destination-Host parameter might contain a different hostname than ours. (which would be the ultimate destination it needs to go)
Is there a hack to achieve this without meddling with the internals of the jdiameter code and RA code?
If you change jdiameter's config to something like this:
<Network>
<Peers>
<Peer name="aaa://127.0.0.1:21812" attempt_connect="false" rating="1" />
<Peer name="aaa://CUSTOM_HOST:4545" attempt_connect="false" rating="1" />
</Peers>
<Realms>
<Realm name="custom.realm" peers="CUSTOM_HOST" local_action="LOCAL" dynamic="false" exp_time="1">
<ApplicationID>
...
</ApplicationID>
</Realm>
</Realms>
</Network>
In your sbb, then you'll need to create a client session providing your custom realm using this method:
DiameterCCAResourceAdaptor.CreditControlProviderImpl.createClientSession(DiameterIdentity destinationHost, DiameterIdentity destinationRealm)
Example:
ccaRaSbb.createClientSession(null, "custom.realm")
where ccaRaSbb is a CreditControlProvider instance (resource adaptor interface)
finally, when creating your CCR, the method CreditControlClientSession.createCreditControlRequest() will use the session' realm to find an available peer previously configured.
Let me know if this makes sense to you
Posting the method I used to solve this problem.
As it turns out its not possible out of the box to send a diameter message towards a peer which is not configured in the stack's jdiameter-config.xml file.
For me, the option to alter the stack in this case was also not feasible. So I devised a workaround for the problem by co-operating with the DRA we have. (most DRA's should be able to handle this method)
I added two custom AVPs to the outgoing request, namely Ultimate-Destination-Host and Ultimate-Destination-Realm.
In the DRA, I asked the admin to delete my Destination-Host and Destination-Realm AVPs and replace them with the ones created in step 1.
Now, whenever I send a packet destined to other diameter peers outside the configured peer, I target them towards the DRA and set these 'Ultimate' destination AVPs.
Ours is an Oracle DSR which is capable of doing this AVP manipulation. Most commercial ones should be able to handle it. Hope someone who wanted an answer for this question found this useful.

Proper way to convey error messages during calls to a REST service?

I'm writing a REST based web service, and I'm trying to figure out the best way to handle error conditions.
Currently the service is returning HTTP Errors, such as Bad Request, but how can I return extra information to give developers using the web service an idea what they're doing wrong?
For example: creating a user with a null username returns an error of Bad Request. How can I add that the error was caused by a null username parameter?
According to the HTTP spec, the text that comes after the three digit response code, the "Reason-Phrase", can only be replaced with a logical equivalent. So you can't respond with 400 null user and expect anything useful to happen. Indeed, The client is not required to examine or display the Reason- Phrase.
In general, the HTTP response entity (typically the page that accompanies the response) should contain information useful to the client to guide them forward, even when the response is an error. On the web, most such errors are HTML, and are devoid of machine readable information, but most browsers do show the error to the user (and SO's error page is pretty good!).
So for a primarily machine readable resource you have two options:
Pass a human readable message anyway. Return 400 Bad Request with a HTML response, which the client may opt to show to the user. It's dead easy but it's a bit like throwing an unchecked exception, it passes all the hard work to the client, or indeed the end user.
Allow clients to recover. Return 400 Bad Request with a machine readable response which is part of your API, so clients can recover from known error conditions. This is harder, like throwing a checked exception, it becomes part of the API, and it allows clients to recover gracefully if they want to.
You could even make the server support both scenarios by defining a media type for the machie readable error recovery document, and allow clients to "accept" them: Accept: application/atom+xml, application/my.proprietary.errors+json
Clients that forget the mandatory field can opt in to getting machine readable errors or human readable errors by choosing to Accepting the error media type.
It's stated in the HTTP spec that most error codes should return some basic text that gives a clarification of why the error is being returned. The basic Java Servlet Spec defines the HttpServletResponse.sendError(int Code, String message) for this purpose.
String desc = "my Description";
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(desc).type("text/plain").build());

BizTalk 2006 SOAP Adapter - Messaging only Web Service Call

In BizTalk 2006, I am trying to set up a messaging-only scenario whereby the recieved message (a string) is passed to a web service method that takes a single string parameter. In other words, the whole body of the BizTalk message should be passed as the parameter to the web service call.
The service method looks like this:
[WebMethod]
public void LogAuditEvent(string auditEventMessage)
I have set up the assembly with the proxy class in the SOAP adapter configuration as required, but I can't figure out how to get the message body to be passed as the parameter. Without doing anything special, I get the following error message:
Failed to serialize the message part
"auditEventMessage" into the type
"String" using namespace "".
I think this means that the adapter cannot find a message part named after the parameter. So, my question is what do I need to do to get my message set up correctly? I was thinking that maybe I needed to add an outbound map, but was not sure what to use as the source schema and how to generate a proper schema for the web service request message.
Does anyone have any pointers on this seemingly simple task?
Thanks.
TDL,
I would take a look at the links below for some tips on how to do this. SOAP adapter can be problematic I would recommend WCF if your using R2. And if not look at the WSE adapters as well.
http://blogs.digitaldeposit.net/saravana/post/2007/01/31/Calling-Web-Service-from-BizTalk-2006-in-a-Messaging-only-Scenario-(aka-Content-based-Routing).aspx
-and-
http://www.pluralsight.com/community/blogs/aaron/archive/2005/10/07/15386.aspx
-and-
http://social.technet.microsoft.com/Forums/en-US/biztalkgeneral/thread/92f2cad3-39b9-47d0-9e6f-011ccd2f9e10/
-Bryan