Add query param at runtime when using CXF proxy client - jax-rs

So I'm using CXF-RS proxy feature to create reusable REST client that I will use in multiple applications. So I have an interface, something like that :
#Path("/hello")
public interface HelloService {
#GET
#Path("sayHello")
String sayHello(#QueryParam("name") String name);
}
And I'm creating the client with :
JAXRSClientFactory.create(address, HelloService.class, Collections.singletonList(JacksonJsonProvider.class), true)
But now I need depending on the configuration of the application to send an additional query parameter to the request. I would like not to change the interface HelloService and instead use some kind of filter to handle this. I saw the ClientRequestFilter but I don't know if it's the right tool and how I should add it to the proxy (all the tutorials I saw use ClientBuilder.newClient() and not a proxy).
Thank you in advance.

Sure you can use a ClientRequestFilter for this. Say you wanted to add a query param. You could do something like
public class MyClientFilter implements ClientRequestFilter {
#Override
public void filter(ClientRequestContext request) throws IOException {
request.setUri(UriBuilder.fromUri(request.getUri())
.queryParam("foo", "bar")
.build());
}
}
To register it, you just add it to the list you pass as the third argument to JAXRSClientFactory.create. Look at the docs for JAXRSClientFactory. You can see the overloaded create methods that accepts a list of providers. The ClientRequestFilter is a kind of provider.

Related

Translate property name in error messages with FluentValidation

I use FluentValidation in my project in order to validate almost every requests coming into my WebApi.
It works fine, but I've been asked to translate property names in the error messages. My projet must handle at least french and english, so for example, what I want to achieve is :
'First Name' is required (english case)
'Prénom' est requis (french case)
I already have a IPropertyLabelService for other purposes, that is injected in the Startup.cs, that I want to use. It finds translations of property names in a .json, which already works fine.
My problem is that I don't know how to use it globally. I know that FluentValidation's doc says to set the ValidatorOptions.DisplayNameResolver in the Startup file, like this :
FluentValidation.ValidatorOptions.DisplayNameResolver = (type, memberInfo, expression) => {
// Do something
};
I don't know how I can use my IPropertyLabelService inside this, as the Startup.ConfigureServices method is not over yet, so I can't resolve my service...
Any other solution to achieve this behaviour is also more than welcome. I considered using .WithMessage() or .WithName() but I have a really big amount of validators, that would be really long to add this to all individually.
I answered this over on the FluentValidation issue tracker, but for completeness will include the answer here too:
Ssetting FluentValidation.ValidatorOptions.Global.DisplayNameResolver is the correct way to handle this globally (or you can use WithName at the individual rule level).
You need to ensure that this is set once, globally. If you need the service provider to have been initialized first, then make sure you call it at a point after the service provider has been configured (but ensure you still only set it once).
The "options" configuration mechanism in .NET Core allows you to defer configuration until after the point services have been constructed, so you can create a class that implements IConfigureOptions, which will be instantiated and executed during the configuration phase for a particular options type. FluentValidation doesn't provide any options configuration itself, so you can just hook into one of the built-in options classes (ASP.NET's MvcOptions is probably the simplest, but you can also use a different one if you're not using mvc).
For example, you could do something like this inside your ConfigureServices method:
public void ConfigureServices(IServiceCollection services) {
// ... your normal configuration ...
services.AddMvc().AddFluentValidation();
// Afterwards define some deferred configuration:
services.AddSingleton<IConfigureOptions<MvcOptions>, DeferredConfiguration>();
}
// And here's the configuration class. You can inject any services you need in its constructor as with any other DI-enabled service. Make sure your IPropertyLabelService is registered as a singleton.
public class DeferredConfiguration : IConfigureOptions<MvcOptions> {
private IPropertyLabelService _labelService;
public DeferredConfiguration(IPropertyLabelService labelService) {
_labelService = labelService;
}
public void Configure(MvcOptions options) {
FluentValidation.ValidatorOptions.Global.DisplayNameResolver = (type, memberInfo, expression) => {
return _labelService.GetPropertyOrWhatever(memberInfo.Name);
};
}
}

What is "DbContextOptions`1"?

I have Web API in ASP .NET Core. When I add a db context in Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<FixturesContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("FixturesDatabase")));
services.AddControllers();
}
I see the number of services in the "services" container raises by three, I think those are:
FixturesContext
DbContextOptions
DbContextOptions`1
I am curious what is "DbContextOptions1"? Does anyone know? I have tried googling it but not satysfying result. My goal is to replace original context with in-memory (to run integration tests without original database), so I'm deleting db context and its options and adding in-memory context instead of them.
The third service you are getting is a generic version of the DbContextOptions. When calling .ToString() on a generic type it often looks like this.
The reason why there are three instances is that EF adds a general DbContextOptions object and a more specific one for your defined context.
If you inspect the calls of the third service you should find the type of your DbContext as a generic parameter.
DbContextOptions'1 would be the generic DbContextOptions<FixturesContext> registered to be injected into the context when being initialized.
Reference Configuring DbContextOptions
public class FixturesContext : DbContext
{
public FixturesContext(DbContextOptions<FixturesContext> options)
: base(options)
{ }
//...
}

Injecting IOptions<> into ApiKeyAuthorizeAttribute

I am using options pattern that stores different configurations, including API keys for different environments. So far I have been using it fine and injecting my values into classes as needed.
However, I faced a little challenge while trying to setup authorization in the controller and run validation against my ApiKey that is unique per environment, because I was not able to inject IOptions into ApiKeyAuthorizeAttribute class to perform validation.
Here is how my controller looks like now:
[ApiKeyAuthorize]
public class NotificationSettingsController : Controller
{
//some endpoints here
}
ApiKeyAuthorize Class:
public class ApiKeyAuthorizeAttribute : Attribute, IAuthorizationFilter
{
//////This...
private readonly IOptions<MyConfig> _config;
public ApiKeyAuthorizeAttribute(IOptions<MyConfig> config)
{
_config = config;
}
/////////...is what I am trying to accomplish
public void OnAuthorization(AuthorizationFilterContext context)
{
var request = context.HttpContext.Request;
var foundApiKeys = request.Headers.TryGetValue("ReplaceWithOptionsApiKeyName", out var requestApiKeys);
if (!foundApiKeys || requestApiKeys[0] != "ReplaceWithOptionsApiKeyValue")
{
context.Result = new UnauthorizedResult();
}
}
}
My problem is that injecting here isn't possible, but I need to get a value from IOptions<> to run ApiKey validation.
Attributes are constructed in-place, so it's not possible to inject dependencies into them. However, ASP.NET Core provides a workaround. Instead of applying the attribute directly, you can use the ServiceFilter attribute instead and pass it the type of the filter you want to apply:
[ServiceFilter(typeof(ApiAuthorizeAttribute))]
This will dynamically apply the filter to the controller/action while instantiating it with any dependencies it requires at the same time. However, it does limit you in the other direction. For example, if you need to do something like:
[ApiAuthorizeAttribute(Roles = "Admin")]
It would not be possible to achieve this with the ServiceFilter attribute, because you cannot pass property values, like Roles here, along with the type.

AutoFac WCF proxy with changing ClientCredentials

I'm writing a WCF service and am using the AutoFac WCF integration for DI. I have a slightly weird situation where I have a proxy to another service that requires credentials. The credentials will change based on some parameters coming in so I can't just set the values when I'm setting up the container and be done with it.
public class MyService : IMyService
{
private ISomeOtherService _client;
public MyService(ISomeOtherService client)
{
_client = client;
}
public Response SomeCall(SomeData data)
{
// how do I set ClientCredentials here, without necessarily casting to concrete implementation
_client.MakeACall();
}
}
What's the best way to set the credentials on proxy without having to cast to a known type or ChannelBase. I'm trying to avoid this because in my unit tests I'm mocking out that proxy interface so casting it back to one of those types would fail.
Any thoughts?
You can do it, but it's not straightforward, and you have to slightly change the design so the logic of "decide and set the credentials" is pulled out of the MyService class.
First, let's define the rest of the classes in the scenario so you can see it all come together.
We have the ISomeOtherService interface, which I've modified slightly just so you can actually see what credentials are getting set at the end. I have it return a string instead of being a void. I've also got an implementation of SomeOtherService that has a credential get/set (which is your ClientCredentials in WCF). That all looks like this:
public interface ISomeOtherService
{
string MakeACall();
}
public class SomeOtherService : ISomeOtherService
{
// The "Credentials" here is a stand-in for WCF "ClientCredentials."
public string Credentials { get; set; }
// This just returns the credentials used so we can validate things
// are wired up. You don't actually have to do that in "real life."
public string MakeACall()
{
return this.Credentials;
}
}
Notice the Credentials property is not exposed by the interface so you can see how this will work without casting the interface to the concrete type.
Next we have the IMyService interface and associated request/response objects for the SomeCall operation you show in your question. (In the question you have SomeData but it's the same idea, I just went with a slightly different naming convention to help me keep straight what was input vs. what was output.)
public class SomeCallRequest
{
// The Number value is what we'll use to determine
// the set of client credentials.
public int Number { get; set; }
}
public class SomeCallResponse
{
// The response will include the credentials used, passed up
// from the call to ISomeOtherService.
public string CredentialsUsed { get; set; }
}
public interface IMyService
{
SomeCallResponse SomeCall(SomeCallRequest request);
}
The interesting part there is that the data we're using to choose the set of credentials is the Number in the request. It could be whatever you want it to be, but using a number here makes the code a little simpler.
Here's where it starts getting more complex. First you really need to be familiar with two Autofac things:
Implicit relationships - we can take a reference on a Func<T> instead of a T to get a "factory that creates T instances."
Using parameters from registration delegates - we can take some inputs and use that to inform the outputs of the resolve operation.
We'll make use of both of those concepts here.
The implementation of MyService gets switched to take a factory that will take in an int and return an instance of ISomeOtherService. When you want to get a reference to the other service, you execute the function and pass in the number that will determine the client credentials.
public class MyService : IMyService
{
private Func<int, ISomeOtherService> _clientFactory;
public MyService(Func<int, ISomeOtherService> clientFactory)
{
this._clientFactory = clientFactory;
}
public SomeCallResponse SomeCall(SomeCallRequest request)
{
var client = this._clientFactory(request.Number);
var response = client.MakeACall();
return new SomeCallResponse { CredentialsUsed = response };
}
}
The real key there is that Func<int, ISomeOtherService> dependency. We'll register ISomeOtherService and Autofac will automatically create a factory that takes in an int and returns an ISomeOtherService for us. No real special work required... though the registration is a little complex.
The last piece is to register a lambda for your ISomeOtherService instead of a simpler type/interface mapping. The lambda will look for a typed int parameter and we'll use that to determine/set the client credentials.
var builder = new ContainerBuilder();
builder.Register((c, p) =>
{
// In WCF, this is more likely going to be a call
// to ChannelFactory<T>.CreateChannel(), but for ease
// here we'll just new this up:
var service = new SomeOtherService();
// The magic: Get the incoming int parameter - this
// is what the Func<int, ISomeOtherService> will pass
// in when called.
var data = p.TypedAs<int>();
// Our simple "credentials" will just tell us whether
// we passed in an even or odd number. Yours could be
// way more complex, looking something up from config,
// resolving some sort of "credential factory" from the
// current context (the "c" parameter in this lambda),
// or anything else you want.
if(data % 2 == 0)
{
service.Credentials = "Even";
}
else
{
service.Credentials = "Odd";
}
return service;
})
.As<ISomeOtherService>();
// And the registration of the consuming service here.
builder.RegisterType<MyService>().As<IMyService>();
var container = builder.Build();
OK, now that you have the registration taking in an integer and returning the service instance, you can just use it:
using(var scope = container.BeginLifetimeScope())
{
var myService = scope.Resolve<IMyService>();
var request = new SomeCallRequest { Number = 2 };
var response = myService.SomeCall(request);
// This will write "Credentials = Even" at the console
// because we passed in an even number and the registration
// lambda executed to properly set the credentials.
Console.WriteLine("Credentials = {0}", response.CredentialsUsed);
}
Boom! The credentials got set without having to cast to the base class.
Design changes:
The credential "set" operation got moved out of the consuming code. If you don't want to cast to the base class in your consuming code, you won't have a choice but to also pull the credential "set" operation out. That logic could be right in the lambda; or you could put it in a separate class that gets used inside that lambda; or you could handle the OnActivated event and do a little magic there (I didn't show that - exercise left to the reader). But the "tie it all together" bit has to be somewhere in the component registration (the lambda, the event handler, etc.) because that's the only point at which you still have the concrete type.
The credentials are set for the lifetime of the proxy. It's probably not good if you have a single proxy in your consuming code where you set different credentials just before you execute each operation. I can't tell from your question if that's how you have it, but... if that's the case, you will need a different proxy for each call. That may mean you actually want to dispose of the proxy after you're done with it, so you'll need to look at using Owned<T> (which will make the factory Func<int, Owned<T>>) or you could run into a memory leak if services are long-lived like singletons.
There are probably other ways to do this, too. You could create your own custom factory; you could handle the OnActivated event that I mentioned; you could use the Autofac.Extras.DynamicProxy2 library to create a dynamic proxy that intercepts calls to your WCF service and sets the credentials before allowing the call to proceed... I could probably brainstorm other ways, but you get the idea. What I posted here is how I'd do it, and hopefully it will at least point you in a direction to help you get where you need to go.
The approach we ended up taking is to cast ISomeOtherService to ClientBase,
This avoids referencing the proxy type. Then in our unit tests we can set up the mock like so
var client = new Mock<ClientBase<ISomeOtherService>>().As<ISomeOtherService>();
So it can be casted to ClientBase, but still setup as ISomeOtherService

generic requests on agatha

does anyone know why I can't do this ?
public class CreateScenarioHandler :
GL.RRSL.RequestHandler<CommandRequest<ScenarioProfileData>,
CommandResponse<ScenarioProfileData>>
why is it imposible for Agatha to figure out the type of the generic Request. It is defined there. ?
Type 'GL.RequestResponse.CommandRequest`1[T]' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types.
any ideas of how to do this. It feels so restrictive to have to create a request object for each type of operation.
I'm actually using generic requests/responses successfully.
The trick was to register closed generic requests/responses as known-types.
In order to achieve this, I'm using the following conventions:
generic requests/responses can have only one generic parameter
that generic parameter should has a generic constraint that specifies that it should implement a given interface
I'm using this convention to construct every possible closed generic type
that I'm going to be using as request or response.
For example, I can have something like this:
interface IDtoWithId
{
int Id { get; }
}
public class GetEntityRequest<TDto> : Request where TDto : IDtoWithId
{
....
}
public class UserDto : IDtoWithId
{
public int Id { get; set; }
public string Name { get; set; }
}
Then, when configuring Agatha, I'm using something like
this https://gist.github.com/916352 and doing:
....
configuration.Initialize();
KnownTypeProvider.ClearAllKnownTypes();
KnownTypeHelper.RegisterRequestsAndResponses(typeof(UserDto).Assembly);
The KnownTypeHelper registers the GetEntityRequest type as a
known-type and that allow me to handle that request using a handler
hierarchy like this:
public abstract class GetEntityHandler<TEntity, TDto> :
RequestHandler<GetEntityRequest<TDto>, GetEntityResponse<TDto>>
{
...
}
public class GetUserHandler : GetEntityHandler<User, UserDto>
{
}
I'm using this approach for the CRUD part of an application and it is
working very well.
The problem here has to do with how CommandRequest and CommandResponse are defined.
Agatha looks at the classes which extends Request and Response and add's them to the known types in the WCF.
When the server starts the service, WCF complains that the type CommandRequest is generic and can't be used. WCF if saying that it can't claim to know about a generic type.
When I define CommandRequest and CommandResponse as abstract, and then create classes like ScenarioIORequest/Response which extend CommandRequest and CommandResponse respectively with the apropiate type to be wrapped, WCF does not complain.
It feels like a waste that I have to define specific types when I would like to have generic requests and responses for different DTO. Maybe this will change at some point, but it seams to be WCF issue rather then the Agatha project issue.