How can I add a Dependency that can be used as type parameter 'TImpl' for Castle Windsor? - asp.net-web-api

I was getting this runtime exception with a particular URL:
"Missing dependency. Component NRBQ.Web.Controllers.DeliveryController has a dependency on SeaStore.Data.Legacy.Interfaces.INRBQDeliveryRepository, which could not be resolved. Make sure the dependency is correctly registered in the container as a service, or provided as inline argument."
ExceptionType: "Castle.MicroKernel.Resolvers.DependencyResolverException"
...so I added this code (based on existing code that works) to the IOC class:
_container.Register
(Component
.For<INRBQDeliveryRepository>()
.ImplementedBy<DeliveryController>()
.LifeStyle.Transient);
In some context:
private static Castle.Windsor.IWindsorContainer _container;
_container = new Castle.Windsor.WindsorContainer();
_container.AddFacility<Castle.Facilities.FactorySupport.FactorySupportFacility>();
. . .
_container.Register
(Component
.For<INRBQDeliveryRepository>()
.ImplementedBy<DeliveryController>()
.LifeStyle.Transient);
...but that won't even compile; I now get:
The type 'NRBQ.API.Controllers.DeliveryController' cannot be used as type parameter 'TImpl' in the generic type or method 'Castle.MicroKernel.Registration.ComponentRegistration.ImplementedBy()'. There is no implicit reference conversion from 'NRBQ.API.Controllers.DeliveryController' to 'SeaStore.Data.Legacy.Interfaces.INRBQDeliveryRepository'.
I know this is probably a bit myseterious (I'm probably omitting some important details in this question), but I'm not sure what additional clues I should add.
UPDATE
In response to whether DeliveryController implements INRBQDeliveryRepository: Actually, there are three controller-type things; a user-facing one in NRBQ.Web:
public class DeliveryController : ApiController
{
private readonly INRBQDeliveryRepository _deliveryRepository;
public DeliveryController(INRBQDeliveryRepository deliveryRepository)
{
if (deliveryRepository == null)
{
throw new ArgumentNullException("DeliveriesController");
}
_deliveryRepository = deliveryRepository;
}
[Route("api/Deliveries/Count")]
public int GetCountOfDeliveryRecords()
{
return _deliveryRepository.GetCount();
}
. . .
...then a middle one in NRBQ.Client:
namespace NRBQ.Client
{
public class RESTNRBQDelivery : INRBQDelivery
{
INRBQClientSettings NRBQClientSettings;
IRESTAPIClient RESTAPIClient;
public RESTNRBQDelivery(IRESTAPIClient RESTAPIClient, INRBQClientSettings NRBQClientSettings)
{
this.NRBQClientSettings = NRBQClientSettings;
this.RESTAPIClient = RESTAPIClient;
}
public RESTNRBQDelivery(IRESTAPIClient RESTAPIClient, INRBQClientSettings NRBQClientSettings, AuthenticationHeaderValue AuthHeader)
{
this.NRBQClientSettings = NRBQClientSettings;
this.RESTAPIClient = RESTAPIClient;
this.RESTAPIClient.AuthHeader = AuthHeader;
}
public int GetCount()
{
throw new NotImplementedException(); //TODO: Implement
}
....and finally the one that really does the behind-the-scenes heavy lifting, in NRBQ.API:
namespace NRBQ.API.Controllers
{
public class DeliveryController : ApiController
{
ILogger Logger;
INRBQService NRBQService;
public DeliveryController(ILogger Logger, INRBQService NRBQService)
{
this.NRBQService = NRBQService;
this.Logger = Logger;
}
[HttpGet]
[Route("api/Deliveries/Count")]
public int GetCountOfDeliveryRecords()
{
//return _deliveryRepository.GetCount();
return NRBQService.GetNRBQEntity();
}
That last call refers to here:
public int GetNRBQEntity()
{
return 17; // Bogus val for now
}
This all is my best attempt at copying existing test/sample code, but I admit that my head is swimming and I don't really grok what's happening (how and why).
UPDATE 2
Although I'm pretty sure it's still not quite a Nathan's hot dog (it seems to chase itself all over creation, calling first this abstraction, then that one, then another, then back to the first, then another, then back to the second, etc. etc. ad infinitum ad nauseum advillium), adding this:
container.Register
(Component
.For<INRBQDelivery>()
.ImplementedBy<RESTNRBQDelivery>()
.LifeStyle.Transient);
...in context:
public class NRBQClientInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register
(Component
.For<SeaStore.Common.HTTP.IRESTAPIClient>()
.ImplementedBy<SeaStore.Common.HTTP.WebAPIClient>()
.LifeStyle.Transient);
container.Register
(Component
.For<INRBQClient>()
.ImplementedBy<RESTNRBQClient>()
.LifeStyle.Transient);
container.Register
(Component
.For<INRBQDelivery>()
.ImplementedBy<RESTNRBQDelivery>()
.LifeStyle.Transient);
}
}
...got rid of the err msg and returned the fake result I was expecting (or, rather, hoping for, not really expecting).

In your IWindsorInstaller unit, register the interface and its implementer:
container.Register
(Component
.For<INRBQDelivery>()
.ImplementedBy<RESTNRBQDelivery>()
.LifeStyle.Transient);

Related

Mockito: Verifying a method was called with a functional parameter

I have a simple scenario in which am trying to verify some behavior when a method is called (i.e. that a certain method was called with given parameter, a function pointer in this scenario). Below are my classes:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
AppBootStrapper bootStrapper = context.getBean(AppBootStrapper.class);
bootStrapper.start();
}
}
#Component
public class AppBootStrapper {
private NetworkScanner networkScanner;
private PacketConsumer packetConsumer;
public AppBootStrapper(NetworkScanner networkScanner, PacketConsumer packetConsumer) {
this.networkScanner = networkScanner;
this.packetConsumer = packetConsumer;
}
public void start() {
networkScanner.addConsumer(packetConsumer::consumePacket);
networkScanner.startScan();
}
}
#Component
public class NetworkScanner {
private List<Consumer<String>> consumers = new ArrayList<>();
public void startScan(){
Executors.newSingleThreadExecutor().submit(() -> {
while(true) {
// do some scanning and get/parse packets
consumers.forEach(consumer -> consumer.accept("Package Data"));
}
});
}
public void addConsumer(Consumer<String> consumer) {
this.consumers.add(consumer);
}
}
#Component
public class PacketConsumer {
public void consumePacket(String packet) {
System.out.println("Packet received: " + packet);
}
}
#RunWith(JUnit4.class)
public class AppBootStrapperTest {
#Test
public void start() throws Exception {
NetworkScanner networkScanner = mock(NetworkScanner.class);
PacketConsumer packetConsumer = mock(PacketConsumer.class);
AppBootStrapper appBootStrapper = new AppBootStrapper(networkScanner, packetConsumer);
appBootStrapper.start();
verify(networkScanner).addConsumer(packetConsumer::consumePacket);
verify(networkScanner, times(1)).startScan();
}
}
I want to verify that bootStrapper did in fact do proper setup by registering the packet consumer(there might be other consumers registered later on, but this one is mandatory) and then called startScan. I get the following error message when I execute the test case:
Argument(s) are different! Wanted:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapperTest$$Lambda$8/438123546#282308c3
);
-> at com.spring.starter.AppBootStrapperTest.start(AppBootStrapperTest.java:24)
Actual invocation has different arguments:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapper$$Lambda$7/920446957#5dda14d0
);
-> at com.spring.starter.AppBootStrapper.start(AppBootStrapper.java:12)
From the exception, clearly the function pointers aren't the same.
Am I approaching this the right way? Is there something basic I am missing? I played around and had a consumer injected into PacketConsumer just to see if it made a different and that was OK, but I know that's certainly not the right way to go.
Any help, perspectives on this would be greatly appreciated.
Java doesn't have any concept of "function pointers"; when you see:
networkScanner.addConsumer(packetConsumer::consumePacket);
What Java actually compiles is (the equivalent of):
networkScanner.addConsumer(new Consumer<String>() {
#Override void accept(String packet) {
packetConsumer.consumePacket(packet);
}
});
This anonymous inner class happens to be called AppBootStrapper$$Lambda$7. Because it doesn't (and shouldn't) define an equals method, it will never be equal to the anonymous inner class that the compiler generates in your test, which happens to be called AppBootStrapperTest$$Lambda$8. This is regardless of the fact that the method bodies are the same, and are built in the same way from the same method reference.
If you generate the Consumer explicitly in your test and save it as a static final Consumer<String> field, then you can pass that reference in the test and compare it; at that point, reference equality should hold. This should work with a lambda expression or method reference just fine.
A more apt test would probably verify(packetConsumer, atLeastOnce()).consumePacket(...), as the contents of the lambda are an implementation detail and you're really more concerned about how your component collaborates with other components. The abstraction here should be at the consumePacket level, not at the addConsumer level.
See the comments and answer on this SO question.

How can I access previously set fields in a seam #Observer method?

My current setup is JBoss Seam 2.2 on JBoss 4.2.3.GA.
I have two Beans like so:
#Name("mailingManager")
#Scope(ScopeType.PAGE)
public class MailingMgr {
private Mailing selectedMailing;
#Observer("mailing.letter.success")
public void recordSuccess(final Object arg) {
if (null != selectedMailing) { // store arg }
}
public void send() {
selectedMailing = new Mailing();
if ('EMAIL' == determineType()) {
EmailSender mailer = (EmailSender) Component.getInstance(EmailSender.class);
mailer.send(getAddresses());
}
// ... more options
}
}
#Name("emailSender")
#Scope(ScopeType.PAGE)
public class EmailSender {
public void send(final Set<String> addresses) {
for (String addr : addresses) {
// ... create a mail
Events.instance().raiseEvent("mailing.letter.success", getGeneratedMail());
}
}
}
The problem is that when recordSuccess() is called selectedMailing is always null.
As a workaround I'm setting selectedMailing in the conversation context manually before calling any code that could potentially trigger my events, and then annotate my field with #In(required=false) to inject it again before recordSuccess is called. But is there a more elegant solution (keeping the decoupling intact)? And why isn't the calling bean reused to handle the event?

How to fake an HttpContext and its HttpRequest to inject them in a service constructor

In a console application, I would like to use a service that would normally need the current http context to be passed to its constructor. I am using Ninject, and I think I can simply fake an http context and define the proper binding, but I have been struggling with this for a few hours without success.
The details:
The service is actually a mailing service that comes from an ASP.Net MVC project. I am also using Ninject for IoC. The mail service needs the current http context to be passed to its constructor. I do the binding as follows:
kernel.Bind<IMyEmailService>().To<MyEmailService>()
.WithConstructorArgument("httpContext", ninjectContext => new HttpContextWrapper(HttpContext.Current));
However, I would like now to use this mailing service in a console application that will be used to run automated tasks at night. In order to do this, I think I can simply fake an http context, but I have been struggling for a few hours with this.
All the mailing service needs from the context are these two properties:
httpContext.Request.UserHostAddress
httpContext.Request.RawUrl
I thought I could do something like this, but:
Define my own fake request class:
public class AutomatedTaskHttpRequest : SimpleWorkerRequest
{
public string UserHostAddress;
public string RawUrl;
public AutomatedTaskHttpRequest(string appVirtualDir, string appPhysicalDir, string page, string query, TextWriter output)
: base(appVirtualDir, appPhysicalDir, page, query, output)
{
this.UserHostAddress = "127.0.0.1";
this.RawUrl = null;
}
}
Define my own context class:
public class AutomatedTasksHttpContext
{
public AutomatedTaskHttpRequest Request;
public AutomatedTasksHttpContext()
{
this.Request = new AutomatedTaskHttpRequest("", "", "", null, new StringWriter());
}
}
and bind it as follows in my console application:
kernel.Bind<IUpDirEmailService>().To<UpDirEmailService>()
.WithConstructorArgument("httpContext", ninjectContext => new AutomatedTasksHttpContext());
Unfortunately, this is not working out. I tried various variants, but none was working. Please bear with me. All that IoC stuff is quite new to me.
I'd answered recently about using a HttpContextFactory for testing, which takes a different approach equally to a console application.
public static class HttpContextFactory
{
[ThreadStatic]
private static HttpContextBase _serviceHttpContext;
public static void SetHttpContext(HttpContextBase httpContextBase)
{
_serviceHttpContext = httpContextBase;
}
public static HttpContextBase GetHttpContext()
{
if (_serviceHttpContext!= null)
{
return _serviceHttpContext;
}
if (HttpContext.Current != null)
{
return new HttpContextWrapper(HttpContext.Current);
}
return null;
}
}
then in your code to this:
var rawUrl = HttpContextFactory.GetHttpContext().Request.RawUrl;
then in your tests use the property as a seam
HttpContextFactory.SetHttpContext(HttpMocks.HttpContext());
where HttpMocks has the following and would be adjusted for your tests:
public static HttpContextBase HttpContext()
{
var context = MockRepository.GenerateMock<HttpContextBase>();
context.Stub(r => r.Request).Return(HttpRequest());
// and stub out whatever else you need to, like session etc
return context;
}
public static HttpRequestBase HttpRequest()
{
var httpRequest = MockRepository.GenerateMock<HttpRequestBase>();
httpRequest.Stub(r => r.UserHostAddress).Return("127.0.0.1");
httpRequest.Stub(r => r.RawUrl).Return(null);
return httpRequest;
}

How to Integrate Prism, Unity, and Enterprise Library

I'm building a WPF application. I'm using Prism 4, and Unity. I want to add two Enterprise Library 5 blocks to the application, Logging and Exception Handling. I have a singleton LoggerFacadeCustom.cs in my Infrastructure class that supports the ILoggerFacade and I've created it in my bootstrapper, and it is generating log files. It "news" up a unity container in its constructor (second code block)
Where do I add the container.resolve for ExceptionManager? How do I connect the Exception handling block to ILoggerFacade in my bootstrapper? How do I get all the exceptions to come out in the same log? Here is my existing bootstrapper.cs
public class Bootstrapper : UnityBootstrapper {
protected override ILoggerFacade CreateLogger() {
return LoggerFacadeCustom.Instance;
}
protected override DependencyObject CreateShell() {
return Container.Resolve<Shell>();
}
protected override void InitializeShell() {
base.InitializeShell();
App.Current.MainWindow = (Window)Shell;
App.Current.MainWindow.Show();
//Other shell stuff...
}
protected override IModuleCatalog CreateModuleCatalog() {
var catalog = new ModuleCatalog();
//These primary modules must register their own services as if they were acting independantly
catalog.AddModule(typeof(XmlCommentMergeModule));
//These support modules require at least one primary module above to be added first
catalog.AddModule(typeof(ToolboxHeaderModule));
catalog.AddModule(typeof(ToolboxFooterModule));
catalog.AddModule(typeof(ToolboxStartModule));
return catalog;
}
}
LoggerFacadeCustom:
public class LoggerFacadeCustom : ILoggerFacade {
private static readonly LoggerFacadeCustom _instance = new LoggerFacadeCustom();
public static LoggerFacadeCustom Instance { get { return _instance; } }
private LoggerFacadeCustom() {
var container = new UnityContainer();
container.AddNewExtension<EnterpriseLibraryCoreExtension>();
_logWriter = container.Resolve<LogWriter>();
}
private readonly LogWriter _logWriter;
public void Write(string message) { Write(message, null); }
public void Write(string message, string category, int priority) {
_logWriter.Write(message, category, priority);
}
public void Write(string message, Dictionary<string, object> properties) {
_logWriter.Write(message, LiteralString.LogCategoryProcess, properties);
}
#region ILoggerFacade Members
public void Log(string message, Category category, Priority priority) {
throw new NotImplementedException();
}
#endregion
}
Your bootstrapper is the Composition Root of your application. You should register all dependencies there. And only there. You should never reference the container directly outside the composition root.
If your classes have a dependency you should inject that dependency using a pattern like constructor injection.
Don't use static classes. Static kills dependency injection and testability and it hides dependencies to a point where everything is referenced from everywhere.
Make your logger facade a constructor parameter. You can do the same with the error handling block.
Don't use the container as a ServiceLocator. That is considered an anti-pattern in modern software architecture.

How can I enrich object composition in StructureMap without invoking setter injection?

I'm trying to build an implementation of the IHttpControllerActivator interface for with with StructureMap, so that I can resolve a dependency of a controller which takes a dependency on the HttpRequestMessage being processed in the MVC Web API pipeline.
My implementation of Create is as follows:
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
return (IHttpController)this.Container
.With(request)
.With(controllerDescriptor)
.GetInstance(controllerType);
}
The Container property is a reference to the StructureMap IContainer instance passed to the activator when it is constructed.
My registration for the controllers uses reflection to obtain all the ApiController implementations:
foreach(var controller in this.GetType().Assembly.GetTypes()
.Where(type => typeof(ApiController).IsAssignableFrom(type)))
{
this.For(controller).Use(controller);
}
Using the debugger, I checked that initialises the controller instances and passes in their dependencies. However, when the ExecuteAsync method is called on the controller, an exception is thrown:
Cannot reuse an 'ApiController' instance. 'ApiController' has to be constructed per incoming message. Check your custom 'IHttpControllerActivator' and make sure that it will not manufacture the same instance.
After some digging and experimentation I discovered this is due to a check performed at the start of ExecuteAsync which checks the Request property of the ApiController to see if it has been assigned a value. If the property has a non-null value, it infers that the controller has already been used to process a request and aborts the operation.
Further to this, I verified that StructureMap attempted to use its setter-injection behaviour when composing the controller and is responsible for Request having a non-null value.
In my registry, I haven't configured any setter-injection, so I'm confused as to why it's being invoked here. A poke around the StructureMap API hasn't yielded any obvious answers as to how I could change the behaviour exhibited.
Am I invoking StructureMap incorrectly? Is there a configuration setting I can leverage to say "never ever assign a property value"?
I think your issue revolves around the way that you are setting up your controllers with StructureMap. In order to get this working correctly, the best way is to hook into the WebAPI stack's dependency injection stack by creating your own implementation of IDependencyResolver. There's a pretty good example of this at http://craigsdevspace.wordpress.com/2012/02/26/using-structuremap-with-web-api/
The basic code, though, might look something like:
IDependencyResolver:
public class _DependencyResolver : _DependencyScope, IDependencyResolver {
public _DependencyResolver(IContainer container) : base(container) { }
public IDependencyScope BeginScope() {
return new _DependencyScope(_container);
}
}
IDependencyScope:
public class _DependencyScope : ServiceLocatorImplBase, IDependencyScope {
protected readonly IContainer _container;
public _DependencyScope(IContainer container) {
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
public override object GetService(Type serviceType) {
if (serviceType == null)
return null;
try {
return (serviceType.IsAbstract || serviceType.IsInterface)
? _container.TryGetInstance(serviceType)
: _container.GetInstance(serviceType);
} catch {
return null;
}
}
protected override object DoGetInstance(Type serviceType, string key) {
if (string.IsNullOrEmpty(key))
return _container.TryGetInstance(serviceType);
return _container.TryGetInstance(serviceType, key);
}
protected override IEnumerable<object> DoGetAllInstances(Type serviceType) {
return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
}
public IEnumerable<object> GetServices(Type serviceType) {
return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
}
public void Dispose() {
//_container.Dispose();
}
}
To hook these classes up to WebAPI, then, you would add the following to Global.asax:
GlobalConfiguration.Configuration.DependencyResolver =
new _DependencyResolver(ObjectFactory.Container);
And either in Global.asax or in your Bootstrapper, you would add the following:
ObjectFactory.Initialize(x => {
x.Scan(scanner => scanner.AddAllTypesOf<ApiController>());
});
This sets up your StructureMap implementation to use the stack's pre-existing injection structure - which should avoid the problem that you're having.

Resources