How to use ResourceProcessorHandlerMethodReturnValueHandler in a spring-hateos project - spring-mvc

When using spring-data-rest there is a post processing of Resource classes returned from Controllers (e.g. RepositoryRestControllers). The proper ResourceProcessor is called in the post processing.
The class responsible for this is ResourceProcessorHandlerMethodReturnValueHandler which is part of spring-hateoas.
I now have a project that only uses spring-hateoas and I wonder how to configure ResourceProcessorHandlerMethodReturnValueHandler in such a scenario. It looks like the auto configuration part of it still resides in spring-data-rest.
Any hints on how to enable ResourceProcessorHandlerMethodReturnValueHandler in a spring-hateoas context?

I've been looking at this recently too, and documentation on how to achieve this is non-existent. If you create a bean of type ResourceProcessorInvokingHandlerAdapter, you seem to lose the the auto-configured RequestMappingHandlerAdapter and all its features. As such, I wanted to avoid using this bean or losing the WebMvcAutoConfiguration, since all I really wanted was the ResourceProcessorHandlerMethodReturnValueHandler.
You can't just add a ResourceProcessorHandlerMethodReturnValueHandler via WebMvcConfigurer.addReturnValueHandlers, because what we need to do is actually override the entire list, as is what happens in ResourceProcessorInvokingHandlerAdapter.afterPropertiesSet:
#Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
// Retrieve actual handlers to use as delegate
HandlerMethodReturnValueHandlerComposite oldHandlers = getReturnValueHandlersComposite();
// Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, invoker));
// Configure the new handler to be used
this.setReturnValueHandlers(newHandlers);
}
So, without a better solution available, I added a BeanPostProcessor to handle setting the List of handlers on an existing RequestMappingHandlerAdapter:
#Component
#RequiredArgsConstructor
#ConditionalOnBean(ResourceProcessor.class)
public class ResourceProcessorHandlerMethodReturnValueHandlerConfigurer implements BeanPostProcessor {
private final Collection<ResourceProcessor<?>> resourceProcessors;
#Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof RequestMappingHandlerAdapter) {
RequestMappingHandlerAdapter requestMappingHandlerAdapter = (RequestMappingHandlerAdapter) bean;
List<HandlerMethodReturnValueHandler> handlers =
requestMappingHandlerAdapter.getReturnValueHandlers();
HandlerMethodReturnValueHandlerComposite delegate =
handlers instanceof HandlerMethodReturnValueHandlerComposite ?
(HandlerMethodReturnValueHandlerComposite) handlers :
new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
requestMappingHandlerAdapter.setReturnValueHandlers(Arrays.asList(
new ResourceProcessorHandlerMethodReturnValueHandler(delegate,
new ResourceProcessorInvoker(resourceProcessors))));
return requestMappingHandlerAdapter;
}
else return bean;
}
}
This has seemed to work so far...

Related

Kafka Streams Serdes having nested generic doesn't work

I have following code which uses functional style to define two functions for kafka topics
#Bean
public Function<KStream<String, CloudEvent<ClassA>>, KStream<String, CloudEvent<ClassB>>> method1() {
....... //lambda
}
#Bean
public Function<KStream<String, CloudEvent<ClassB>>, KStream<String, CloudEvent<ClassC>>> method2() {
...... //lambda
}
For these two functions I define serdes so
#Bean
public Serde<CloudEventMessage<ClassA>> classASerde(ObjectMapper mapper, Validator validator) {
return StreamsSerdes.classASerde(mapper,validator);
}
#Bean
public Serde<CloudEventMessage<ClassB>> classBSerde(ObjectMapper mapper, Validator validator) {
return StreamsSerdes.classBSerde(mapper,validator);
}
This construction doesn't work as at runtime spring tries to deserialize CloudEvent<ClassB> with Serde of CloutEvent<ClassA>. Is there someway to give hint to use the correct serde for method1 and method2 ?
Secondly I could bypass the above issues by mentioning Serdes in application.properties
spring.application.cloud.stream.kafka.streams.bindings.method1-in-0.consumer.valueSerde=package.serde.StreamsSerdes$ClassASerde
spring.application.cloud.stream.kafka.streams.bindings.method2-in-0.consumer.valueSerde=package.serde.StreamsSerdes$ClassBSerde
However now I get other issues as these Serde classes don't have default constructor. I do need ObjectMapper, Validator from Spring to inject beans (#Service) to perfrom converstions/validations during deserialization.
Has anyone come across similar issues or perhaps have ideas how to resolve them ?
Thanks
I think it is a gap that the nested generics are not working right now in the binder. Do you mind creating an issue in the repository and linking this thread?
As to the second issue that you are running into when providing properties in application.properties, you can try using a workaround. The Serde interface has a configure method that takes a map.
default void configure(Map<String, ?> configs, boolean isKey) {
// intentionally left blank
}
Override this method in your Serde implementation and set those bean objects under some keys.
ObjectMapper mapper;
Validator validator;
#Override
public void configure(Map<String, ?> configs, boolean isKey) {
this.mapper = (ObjectMapper) configs.get("mapper.key");
this.validator = (Validator) configs.get("validator.key");
}
You need to remove accessing them from the constructor and use those fields directly for deserialization and serialization.
Then you provide this bean in your application to populate the map:
#Bean
public StreamsBuilderFactoryBeanCustomizer streamsBuilderFactoryBeanCustomizer(ObjectMapper mapper, Validator validator) {
return factoryBean -> {
factoryBean.getStreamsConfiguration().put("mappeer.key", mapper);
factoryBean.getStreamsConfiguration().put("validator.key", validator);
};
}
I haven't tried this code in an application, but it is something that you can try and see if it works with your code.

DbContext gets disposed in ActionFilterAttribute, not reloaded on subsequent requests

I'm trying to inject a UOW container into a WebApi 2 actionfilter attribute
public class VerifyApiToken : ActionFilterAttribute
{
[Inject]
public IUOW Uow { get; set; }
public override void OnActionExecuting(HttpActionContext actionContext)
{
//get and save data to any repository in the uow container
base.OnActionExecuting(actionContext);
}
The UOW container gets injected like its supposed to and on the first request everything works fine. On subsequent request EF throws an exception saying that the DbContext has been disposed.
All the dependancies are bound in request scope, so its normal that the underlying dbcontext gets disposed. When using constructor injection in WebApi controllers everything works, resources are recreated on each request, why are they not recreated when trying to use Property injection in ActionFilterAttributes and how could this be resolved?
The IFilterProvider I'm using:
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
IEnumerable<FilterInfo> controllerFilters = actionDescriptor.ControllerDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Controller));
IEnumerable<FilterInfo> actionFilters = actionDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Action));
IEnumerable<FilterInfo> filters = controllerFilters.Concat(actionFilters);
foreach (FilterInfo filter in filters)
{
_kernel.Inject(filter.Instance);
}
return filters;
}
The "Inject" method description says "Injects the specified instance, without managing its lifecycle". So I take it that my VerifyApiToken attribute is injected once per App lifecycle (basically Application_Start) and thus on the following requests the same instance is used (with a disposed DbContext of course).
Is it even possible to configure Ninject to use a new IUOW container for each request in ActionFilterAttributes?
Filters are cached and reused by the WebApi Framework. You should thus not inject any dependency in request scope; use a factory instead.
For more information see the documentation
I was able to follow qujck's hint and instead inject a Func to the actionfilter.
It is required the following binding:
kernel.Bind<Func<IUOW>>().ToMethod(m => () => m.Kernel.Get<IUOW>());

Web API controller parameterized constructor called only once, parameterless constructor on subsequent requests

I'm attempting to use Unity to inject a dependency per this article:
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
Here is what I have in my global.asax
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterType<CustomerController>();
unity.RegisterType<TPS.Data.Can.IUnitOfWork, TPS.Data.Can.EFRepository.UnitOfWork>(new HierarchicalLifetimeManager());
config.DependencyResolver = new IoCContainer(unity);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureApi(GlobalConfiguration.Configuration);
}
Here is my API controller:
public class CustomerController : ApiController
{
private TPS.Data.Can.IRepository<tblCustomer> _repo;
private TPS.Data.Can.IUnitOfWork _uow;
public CustomerController() { }
public CustomerController(TPS.Data.Can.IUnitOfWork uow) {
_uow = uow;
_repo = uow.CustomerRepository;
}
// GET api/customer/5
public IEnumerable<Customer> Get()
{
string identity = HttpContext.Current.User.Identity.Name;
//REFACTOR THIS
if (String.IsNullOrWhiteSpace(identity))
identity = "chardie";
var customers = from c in _repo.Get()
where c.SalesRep == identity
select new Customer
{
IDCUST = null,
CustCode = c.CustCode,
CustName = c.CustName
};
return customers.ToList();
}
This works when I first start debugging my application. If I set a breakpoint in the parameterized constructor, the breakpoint will be hit when I hit the Web API for the first time. When I hit refresh in my browser, the constructor does not get called, the dependency doesn't get injected, and the Get() action throws an exception because the expected repository is null.
Can anyone tell me why my constructor isn't being called after the first request?
Thanks!
Chris
EDIT
FWIW, I removed the parameterless constructor entirely from the Web API controller, and on my second request to it, I get the exception:
Type 'TPS.Website.Api.CustomerController' does not have a default constructor
So it appears I'm getting my repo dependency injected on the first request, but after that every instantiation of the Web API controller is done through the parameterless constructor.
You're not specifying a lifecycle for the controller. MSDN states
If you do not specify a value for the lifetime, the instance will have
the default container-controlled lifetime. It will return a reference
to the original object on each call to Resolve.
If the IUnitOfWork dependency is transient, then the controller should be transient too. So try
unity.RegisterType<CustomerController>(new TransientLifetimeManager());
This might not solve the whole problem but it sounds like part of it. You certainly shouldn't need the parameterless constructor.
I had this as I was returning my resolver for my dependency scope using this and then disposing the container in the dispose. So after the first request the container was disposed.
Looks like it's because you're not using singleton pattern for the Unity Container.
Have a private static variable instead of the var container = new UnityContainer();
internal static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => new UnityContainer());
Then access within code using the .Value property.

Verifying indirectly called methods with Moq on a mocked object

My app has a ProviderFactory static class that has static utility methods passing back static instances of things like a logger. The rest of my app then can just grab a/the reference to the logger from anywhere without having to pass in the logger (common design practice).
So, another part of my app, the DbCacheProvider, has methods that make calls to the logger so internally it gets a reference to the logger from the factory and then issues calls to it.
My question is that using Moq, I want to verify methods on the logger are being called by the methods within the DbCacheProvider. I can do this using dependency injection when I pass a mock logger into the DbCacheProvider as a parameter, but I'm not passing the logger in (not do I want to). So, how would I verify the DbCacheProvider is making calls to the logger?
If you don't want to pass the logger in through the constructor you'd need to change your ProviderFactory while running unit tests to return your mocked logger.
Anyway there are a couple of reasons it's often suggested to set up dependency injection:
Your tests are more straightforward and don't involve finagling with custom factories
IoC frameworks like Unity, Ninject and Autofac make it easy to create objects when their dependencies are set up this way. If you set up all of your objects this way, the framework will do all the heavy lifting of creating the right objects and passing them in for you. The dependency injection is done automatically and won't be a burden for you.
Old question without an answer, I had a similar problem and solved it like this:
I have the following sample code and need to verify that not only was a method called but was called with a specific value.
public interface ILog
{
void Info(string message);
}
public interface ILogFactory
{
ILog GetLogger();
}
This is the class being tested, where the interface items are being injected:
public class NewAction
{
readonly ILogFactory _logger;
public NewAction(ILogFactory logger)
{
_logger = logger;
}
public void Step1()
{
_logger.GetLogger().Info("Step 1");
}
public void Step2()
{
_logger.GetLogger().Info("Step 2");
}
}
This is obviously a very simplistic view of my actual code, but I needed to verify that Step1 and Step2 are behaving as expected and passed the correct values to the Log, this would mean I also needed to ensure they occurred in the right order. My test:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// Arrange
var log = new Mock<ILog>();
var factory = new Mock<ILogFactory>();
factory.Setup(l => l.GetLogger()).Returns(log.Object);
// Act
var action = new NewAction(factory.Object);
action.Step1();
action.Step2();
// Assert
factory.Verify(l => l.GetLogger());
log.Verify(l => l.Info(It.Is<string>(s => s == "Step 1")));
log.Verify(l => l.Info(It.Is<string>(s => s == "Step 2")));
}
}
Hope this helps.

ASP.NET - Create custom context object?

How do I create a globally accessible Context object similar to the HttpContext object?
I want to create a custom class library which I want to reference from a website project. In the website project I want to be able to call the following globally:
ClassLibraryName.Context
I cannot create a global property directly in my classlibrary, so how should this be implemented? (I've seen other applications/products use this approach, one of which is Sitecore which has a custom Sitecore.Context object available)
Edit
Might this be a 'valid' solution?
namespace MyLibrary
{
public class Context
{
public static object ContextualObject
{
get;
set;
}
}
}
Yes, this is not hard to implement, if you always run this class in the context of an ASP.NET application, use this approach:
namespace MyLibrary
{
public class Context
{
public static object ContextualObject
{
get
{
var ctx = System.Web.HttpContext.Current.Items[typeof(Context)];
if (ctx == null)
{
ctx = new Context();
System.Web.HttpContext.Current.Items.Add(typeof(Context), ctx);
}
return ctx;
}
set { System.Web.HttpContext.Current.Items[typeof(Context)] = ctx; }
}
}
}
Essentially wrapping the existing HTTP context to provide your own service. This approach also doesn't store the object while the app lives, it only creates it for the current context, and when that response ends, it will die, and be regenerated during the next lifecycle. If that is not OK, store a static reference to context.
I've used this approach similarly in a class library I have at http://nucleo.codeplex.com, it works well.
HTH.
It depends on the lifetime you want the Context object to have. If you want all clients to use the same context, you can go with a singleton implementation.
If you want the context to be unique for each thread or http request you have to use a per request/thread implementation. One way to implement a per http request implementation would be to have a HttpModule create the object at every BeginRequest event and stick it in the HttpContext Items collection.
public static object ContextualObject
{
get { return HttpContext.Current.Items["MyContext"];}
}
You could create an instance of the object on Session_Start in the Global.asax.

Resources