Accessing Endpoint from ExceptionMapper in Jersey - jax-rs

I'm puzzled on how would I be able to fetch the current request handler (org.glassfish.jersey.server.internal.process.Endpoint) in an ExceptionMapper... Take a look at following code...
public class ValidationExceptionMapper implements ExceptionMapper<ValidationException> {
#Override
public Response toResponse(ValidationException exception) {
// Here I would like to know which endpoint triggered this exception...
}
}
Handling of the exceptions would be based on what kind of annotations were present on the input data that failed validations.
Jersey's Endpoint seems to have all the information that I might need. I would prefer to use any option that JAX-RS conforms to. But at this point, I'm ready to look for any alternatives.
Note: I did look at ConstraintViolation.getRootBean()... It points out at the resource rather than at the method that gets invoked... I'm interested in fetching the endpoint rather than just the resource.
Thanks in advance!

Related

Is it possible to have multiple handlers for the same exception leveraging RESTEasy's ExceptionMapper?

When handling RESTEasy exceptions, it is typically very straightforward to perform custom exception handling (in this case, the intent is to handle marshalling issues when receiving an HTTP request):
#Provider
class MissingKotlinParameterExceptionHandler : ExceptionMapper<MissingKotlinParameterException> {
override fun toResponse(exception: MissingKotlinParameterException?): Response {
println("my MissingKotlinParameterException mapper")
return Response.serverError().build()
}
}
The particular challenge I'm experiencing, however, is when the same exception is thrown from different endpoints. For example, having /service1/foo and /service2/bar, due to architect specifications, return completely separate error payloads. Is it possible to separate the implementations based on some sort of configuration, or package structure?
You can inject the resource info into the ExceptionMapper class using:
#Context ResourceInfo info; // this is the java version
Then in the toResponse use that field in order to determine the resource method that serviced the request.

Accessing message headers outside handler functions with nservicebus

I am using nservicebus 7 in my asp.net core 2.1 application.
I wanted to access my custom message headers outside handler functions(specifically in a repository class).
Saw this answer, but somehow both options are not working for me. Whenever I am trying to access ContextAccessor.get, a null references is getting returned.
Any idea what could be wrong or any other way to access IMessageHandlerContexts outside handler functions.
IMessageHandlerContext is only available inside a handler. However, you can pass it as a parameter to other parts of your code.
For example,
public async Task Handle(MyCommand message, IMessageHandlerContext context)
{
var result = await SomeOtherFunction(message, context).ConfigureAwait(false);
}
You could also read the headers in the handler and pass just those to your repository method. See Manipulating message headers. Relevant part below.
public class ReadHandler :
IHandleMessages<MyMessage>
{
public Task Handle(MyMessage message, IMessageHandlerContext context)
{
var headers = context.MessageHeaders;
var nsbVersion = headers[Headers.NServiceBusVersion];
var customHeader = headers["MyCustomHeader"];
return Task.CompletedTask;
}
}
I think the IUniformSession might solve your issue.
I was looking on how to inject IMessageHandlerContext using a DI container but it seems it was initially a design choice of the NServiceBus team to force us to pass this object around.
Then they must have added the uniform session feature.
I haven't used it myself (yet) but I'm starting to believe that's the way to go.
For reference:
https://docs.particular.net/nservicebus/messaging/uniformsession
https://github.com/Particular/NServiceBus.Host/issues/117
Personally, I would try to capture the information required from the headers using a pipeline behavior. The information can be stored in a type defined by yourself, which can be registered in the container and then injected into the repository. That way, you don't need to pass on the IMessageHandlerContext to the repository.
A colleague of mine has a sample for this:
https://github.com/ramonsmits/NServiceBus.InjectStorageContext/tree/v7

is JAXRS resource can use for different requests?

I am using JAXRS to communicate between two application using http request.
During implementation I had an argue with my college, who said I can't use the same resource (org.apache.wink.client.Resource) for different request, as it can cause collision.
I argue that such thing can't happen, and by using the same resource for all requests, I am improving performance.
Bellow is a code snippet, please help to resolve our dispute
public class jaxrsDeliveryService{
private Resource queryResource;
public void init(){
servletPath = url + REMOVE_COUNT_SUFFIX_URL;
queryResource = restClient.resource(servletPath);
queryResource.contentType(APPLICATION_XML).accept(APPLICATION_XML);`
}
public QueryResponse getqueryResult(QueryInfoRequest qir){
ClientResponse response = resource.put(qir);
return response.getEntity(QueryResponse.class);
}
}
Resource is an interface that says nothing about thread-safety. Thus, we should assume that its implementation may be unsafe. If you want to make your class thread-safe you 1) should not use the same Resource, or 2) put its use into synchronized block.
If you don't worry about thread safety, reuse the resource. You will gain a little performance.

NHibernate + WCF + Windows Service and WcfOperationSessionContext class

I have a Windows Service Application
in which i create WCF services in it.
One of the services is data
services: add, delete,
read , updatte data via
WCF.
WCF use NHibernate for data manipulation
So my guestions are:
Any advice (best practice) for session management for Hibernate using with WCF?
Anybody knows anything about
WcfOperationSessionContext (hibernate 3.0) class?
how to use it with WCF?
Well to make it concrete :
Suppose that i have WCF Service called DataServices
class WCFDataService .....
{
void SaveMyEntity(MyEntity entity)
{
.....................?? // How to do? Best Way
// Should i take one session and use it all times
// Should i take session and dipsose when operation finished then get
//new session for new operations?
// If many clients call my WCF service function at the same time?
// what may go wrong?
// etc....
}
}
And I need a NHibernateServiceProvider class
class NHibernateServiceProvider ....
{
// How to get Session ?? Best way
ISession GetCurrentSession(){.... }
DisposeSession(){ ....}
}
Best Wishes
PS: I have read similiar entries here and other web pages. But can not see "concrete" answers.
The WcfOperationSessionContext, similar to ThreadStaticSessionContext and WebRequestSessionContext is an implementation for a session context. The session context is used to bind (associate) a ISession instance to a particular context.
The session in the current context can be retrieved by calling ISessionFactory.GetCurrentSession().
You can find more information about session context here.
The WcfOperationSessionContext represents a context that spans for the entire duration of a WCF operation. You still need to handle the binding of the session in the begining of the operation and the unbinding/commiting/disposal of the session at the end of the operation.
To get access to the begin/end actions in the wcf pipeline you need to implement a IDispatchMessageInspector. You can see a sample here.
Also regarding WCF integration: if you use ThreadStatic session context it will appear to work on development, but you will hit the wall in production when various components (ex: authorization, authentication ) from the wcf pipeline are executed on different threads.
As for best practices you almost nailed it: Use WcfOperationSessionContext to store the current session and the IDispatchMessageInspector to begin/complete your unit of work.
EDIT - to address the details you added:
If you configured WcfOperationSessionContext and do the binding/unbinding as i explained above, all you have to do to is inject the ISessionFactory into your service and just use factory.GetCurrentSession(). I'll post a sample prj if time permits.
Here is the sample project
The model we use for managing NHibernate sessions with WCF is as follows:
1) We have our own ServiceHost class that inherits from System.ServiceModel.ServiceHost which also implements ICallContextInitializer. We add the service host instance to each of the operations in our service as follows:
protected override void InitializeRuntime()
{
base.InitializeRuntime();
foreach (ChannelDispatcher cd in this.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
foreach (DispatchOperation op in ed.DispatchRuntime.Operations)
{
op.CallContextInitializers.Add(this);
}
}
}
}
public void AfterInvoke(object correlationState)
{
// We don't do anything after the invoke
}
public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
OperationContext.Current.Extensions.Add(new SessionOperationContext());
return null;
}
The BeforeInvoke simply makes sure that the OperationContext for each WCF call has it's own session. We have found problems with IDispatchMessageInspector where the session is not available during response serialisation - a problem if you use lazy loading.
2) Our SessionOperationContext will then be called to attach itself and we use the OperationCompleted event to remove ourselves. This way we can be sure the session will be available for response serialisation.
public class SessionOperationContext : IExtension<OperationContext>
{
public ISession Session { get; private set; }
public static SessionOperationContext Current
{
get
{
OperationContext oc = OperationContext.Current;
if (oc == null) throw new InvalidOperationException("Must be in an operation context.");
return oc.Extensions.Find<SessionOperationContext>();
}
}
public void Attach(OperationContext owner)
{
// Create the session and do anything else you required
this.Session = ... // Whatever instantiation method you use
// Hook into the OperationCompleted event which will be raised
// after the operation has completed and the response serialised.
owner.OperationCompleted += new EventHandler(OperationCompleted);
}
void OperationCompleted(object sender, EventArgs e)
{
// Tell WCF this extension is done
((OperationContext)sender).Extensions.Remove(this);
}
public void Detach(OperationContext owner)
{
// Close our session, do any cleanup, even auto commit
// transactions if required.
this.Session.Dispose();
this.Session = null;
}
}
We've used the above pattern successfully in high-load applications and it seems to work well.
In summary this is similar to what the new WcfOperationSessionContext does (it wasn't around when we figured out the pattern above;-)) but also overcomes issues surrounding lazy loading.
Regarding the additional questions asked: If you use the model outlined above you would simply do the following:
void SaveMyEntity(MyEntity entity)
{
SessionOperationContext.Current.Session.Save(entity);
}
You are guaranteed that the session is always there and that it will be disposed once the WCF operation is completed. You can use transactions if required in the normal way.
Here is a post describing, in detail, all the steps for registering and using the WcfOperationSessionContext. It also includes instructions for using it with the agatha-rrsl project.
Ok, after few days of reading internet posts etc. all approaches shown in the internets seems to be wrong. When we are using UnitOfWork pattern with NH 3^ with nhibernate transaction this all aprochaes are producing exceptions. To test it and proof that we need to create test enviroment with MSMQ transaction queue, special interface with OneWay operation contract with transaction required set on it. This approach should works like this:
1. We put transactionally message in queue.
2. Service is getting transactionally messege from queue.
3. Everything works queue is empty.
In some cases not so obious with internet approaches this does not work properly. So here are expamples which we tested that are wrong and why:
Fabio Maulo approach: Use ICallContextInitializer - open NH session/transaction on BeforeCall, after that WCF is executing service method, on AfterCall in context initializer we call session.Flush + transaction.commit. Automaticly session will be saved when transaction scope will commit operation. In situation when on calling transaction.Complete exception will be thrown WCF service will shutdown! Question can be ok, so take transaction.Complete in try/catch clausule - great! - NO wrong! Then transaction scope will commit transaction and message will be taken from queue but data will not be saved !
Another approach is to use IDispatchMessageInspector - yesterday I thought this is best approach. Here we need to open session/transaction in method AfterReceiveRequest, after WCF invoke service operation on message dispatcher inspector BeforeSendReply is called. In this method we have info about [reply] which in OneWay operation is null, but filled with fault information if it occured on invoking service method. Great I thought - this is this ! but NOT! Problem is that at this point in WCF processing pipe we have no transaction ! So if transaction.Complete throw error or session.Flush will throw it we will have not data saved in database and message will not come back to queue what is wrong.
What is the solution?
IOperationInvoker and only this!
You need to implement this interface as a decorator pattern on default invoker. In method Invoke before call we are openning session/transaction open then we call invoke default invoker and after that call transaction.complete in finally clausule we call session.flush. What types of problem this solves:
1. We have transaction scope on this level so when complete throws exception message will go back to queue and WCF will not shutdown.
2. When invocation will throw exception transaction.complete will not be called what will not change database state
I hope this will clear everyones missinformation.
In some free time I will try to write some example.

Passing Validation exceptions via WCF REST

I am using WCF and REST, and I have complex types, which are working fine. Now I need to check for validation, I am thinking of using DataAnnotations e.g.
public class Customer
{
[Required]
public string FirstName {get;set;}
}
Now where the issue is how do I pass this validation down to the REST service?
ALso I need to validate the object when it comes back, and throw an exception, if I am to throw an exception then what is the best way of doing this using REST?
I would use the Validation Application Block included in the Microsoft Enterprise Library to validate the data transfer objects being used in the service interface. You can use attributes to decorate the objects' properties with validation rules, much in the same way as with the ASP.NET Data Annotations.
In case validation fails you should return an appropriate HTTP Error Code and include the details of what went wrong in the HTTP response.
Here is an example:
public void PostCustomer(Customer instance)
{
ValidationResults results = Validation.Validate(instance);
if (!results.IsValid)
{
string[] errors = results
.Select(r => r.Message)
.ToArray();
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
WebOperationContext.Current.OutgoingResponse.StatusDescription = String.Concat(errors);
}
// Proceed with custom logic
}
If you are using the WCF REST Starter Kit, you should instead throw a WebProtocolException, as described in this article.
I would look into writing a custom IDispatchMessageInspector implementation where, in the AfterReceiveRequest method, you manually invoke the validation architecture.
I won't go into the details of how to call the Data Annotations validation architecture as I'm sure you can find that somewhere online if you don't already know how to do it. That said, once you have your validation results you can enumerate them and then, if there are any failed validations, you can throw a generic validation fault filled with the details from the AfterReceiveRequest implementation.