users@jersey.java.net

[Jersey] Re: Retrieving HttpRequestContext in Service Request

From: sdoca sdoca <sdoca_at_shaw.ca>
Date: Fri, 13 Apr 2012 17:37:35 -0600

Hi,

Based on the thread linked to below, I tried to pass the transaction ID as an HTTP header.  Here's what I've got:

My Processor class which puts its a value in the logging MDC as a transactionId and uses a REST service client for some processing:

public Processor
{
    RESTClient myRESTClient = new RESTClient("http://path/to/restService");

    public void process(final Object object)
    {
        //Put the object ID in the logging MDC
        log.debug("Putting '{}' in the MDC as the {} header value.",  object.getObjectID(), "transactionID");
        MDC.put("transactionID", object.getObjectID());

    //Do some stuff

    Object anotherObject = myRESTClient.doQuery(object.getValue());

    //Do more some stuff
    }
}

My RESTClient to access the REST service.  It's here that I'm pulling the transactionId out of the MDC and adding it as a header to the request:

public RESTClient
{
    public Object doQuery(String value)
    {
        Object object = null;

        try
        {
            Builder builder = myRestService.queryParam(PARAM_KEY_VALUE, value)
                    .accept(MediaType.APPLICATION_XML);

            String transactionId = (String) MDC.get("transactionID");

            logger.debug("Retrieved '{}' from MDC for key {}",
                transactionId,
                "transactionID");

            if (this.getTransactionID() != null)
            {
                builder = builder.header("transactionID", transactionId);
            }

            object = builder.get(Object.class);
        }
        catch (Throwable ex)
        {
            //Do error handling
        }
    }
}

My REST service Resource class which should have the transactionId in its request headers and places it in its logging MDC:

@Path("/myPath")
public class MyResource
{
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Object doQuery( @QueryParam("value") String value)
    {
        putTransactionIdInMDC();

        SubscriberAccount account = null;

        try
        {
            //Do query stuff
        }
        catch (Exception ex)
        {
            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
        }

        return account;
    }

    private void putTransactionIdInMDC()
    {
        if (httpContext != null)
        {
            String transactionID = httpContext.getRequest()
                    .getHeaderValue("transactionID");

            if (transactionID != null && transactionID.isEmpty())
            {
                /*
                 * It's not likely, but possible that two headers with the same
                 * header key were put in the request. If so, the value will be
                 * a comma separated list. We're using the first one.
                 */
                String[] strings = transactionID.split(",");

                logger.debug("Header '{}' value(s): {}",
                        "transactionID",
                        strings);

                MDC.put("transactionID", strings[0]);
            }
            else
            {
                logger.debug("The header '{}' was not included in the request.",
                        "transactionID");
            }
        }
        else
        {
            logger.info("Could not get an HttpContext for the request");
        }
    }
}


Based on my logging, I know that the transactionId is being put in the Processor MDC and being pulled from it by the RESTClient class.  However, it's not getting passed as an http header to the REST service.  Can anyone tell me why not?

Processor Log File:

------------------------

2012-04-13T17:30:36.541 MDT  INFO [Ejb-Async-Thread-2] DEBUG
my.package.Processor - Putting '12311497-2279-4516-af7d-cf9716f7748a' in
 the MDC as the transactionId header value.



2012-04-13T17:30:36.541 MDT  INFO [Ejb-Async-Thread-2] DEBUG
my.package.RESTClient- Retrieved '12311497-2279-4516-af7d-cf9716f7748a'
from MDC for key transactionId



REST Service Log File:

-----------------------------

2012 Apr 13 17:30:36,337 MDT [http-thread-pool-80(3)] DEBUG
my.package.MyResource - The header 'transactionId' was not included in the request.




----- Original Message -----
From: Farrukh Najmi <farrukh_at_wellfleetsoftware.com>
Date: Wednesday, April 11, 2012 6:54 am
Subject: [Jersey] Re: Retrieving HttpRequestContext in Service Request
To: users_at_jersey.java.net

>
> Not sure of the details of your post but here is something from
> the archives that may help:
>
> http://markmail.org/message/ggrailrz67ugpzgv
>
> On 04/10/2012 12:55 PM, sdoca sdoca wrote:
> >Hi,
> >
> >I am looking for a way to pass a transaction ID to a web
> service call to be used for logging/tracking purposes (see
> http://stackoverflow.com/questions/9915361/how-to-follow-
> individual-transaction-in-logs-java-ee for more background).
> >
> >I found the ability to add/retrieve HTTP headers in Jersey
> using HttpRequestContext.  I modified my resource to get
> the HttpRequestContext in the method signature and then to
> retrieve the transaction ID from the header and place that into
> the slf4j MDC for use in logging:
> >
> >    @POST
> >    @Consumes(MediaType.APPLICATION_XML)
> >    @Path("/subscriber")
> >    public void createSubscriberAccount(final
> SubscriberAccount account,
> >            @Context HttpRequestContext requestContext)
> >    {
> >       
> putTransactionIdInMDC(requestContext);>
> >        try
> >        {
> >            provisionService.createSubscriberAccount(account);
> >        }
> >        catch (Exception ex)
> >        {
> >            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
> >        }
> >    }
> >
> >    private void
> putTransactionIdInMDC(HttpRequestContext requestContext)
> >    {
> >        String transactionID
> = requestContext.getHeaderValue(Constants.MDC_KEY_TRANSACTION_ID);
> >
> >        if (transactionID !=
> null && transactionID.isEmpty())
> >        {
> >            String[] strings = transactionID.split(",");
> >            MDC.put(Constants.MDC_KEY_TRANSACTION_ID, strings[0]);
> >        }
> >    }
> >
> >However, adding the HttpRequestContext parameter to my method
> signature results in this deploy error:
> >
> >SEVERE: Method, public void
> my.resource.ProvisionResource.createSubscriberAccount(my.SubscriberAccount, com.sun.jersey.api.core.HttpRequestContext), annotated with POST of resource, class my.resource.ProvisionResource, is not recognized as valid resource method.
> >
> >Is there  a different way for me to get the
> HttpRequestContext from the service request?
> >
> >Thanks!
>
>
> --
> Regards,
> Farrukh Najmi
>
> Web: http://www.wellfleetsoftware.com
>
>
>