I'm trying to use StructureMap with nServiceBus.
The Project:
Uses a GenericHost Endpoint to send command messages
Configures nServiceBus using the StructMapBuilder.
Uses a simple StructureMap registry config
Uses a start up class TestServer supporting IWantToRunAtStartup
The TestServer class has ctor dependency on a TestManager class
The TestManager class has ctor dependency on IBus
ObjectFactory.WhatDoIHave() shows StructureMap knows how to construct the classes.
When run I get buildup errors. nServiceBus seems to be overwriting the config?
Note that when I add a IBus ctor depenendency to my event handlers without any other config all appears fine.
Error:
Exception when starting endpoint, error has been logged. Reason: Error creating object with name 'nSeviceBusStructureMapTest.TestServer' : Unsatisfied dependency expressed through constructor argument with index 0 of type [nSeviceBusStructureMapTest.ITestManager] : No unique object of type [nSeviceBusStructureMapTest.ITestManager] is defined : Unsatisfied dependency of type [nSeviceBusStructureMapTest.ITestManager]: expected at least 1 matching object to wire the [miningServiceManage] parameter on the constructor of object [nSeviceBusStructureMapTest.TestServer]
Source:
using System;
using System.Diagnostics;
using NServiceBus;
using StructureMap;
using StructureMap.Configuration.DSL;
namespace nSeviceBusStructureMapTest
{
public class TestSmRegistry : Registry
{
public TestSmRegistry()
{
For<ITestManager>().Use<TestManager>();
For<TestServer>().Use<TestServer>();
}
}
public class TestEndPoint : AsA_Server, IConfigureThisEndpoint
{
public void Init()
{
Configure.With().StructureMapBuilder(ObjectFactory.Container);
ObjectFactory.Configure(c => c.AddRegistry<TestSmRegistry>());
Debug.WriteLine(ObjectFactory.WhatDoIHave());
}
}
public class TestServer : IWantToRunAtStartup
{
public TestServer(ITestManager miningServiceManage)
{
_miningServiceManage = miningServiceManage;
}
private readonly ITestManager _miningServiceManage;
public void Run()
{
_miningServiceManage.Run();
}
public void Stop() { }
}
public interface ITestManager
{
void Run();
}
public class TestManager : ITestManager
{
public TestManager(IBus bus)
{
_bus = bus;
}
private readonly IBus _bus;
public void Run()
{
if (_bus == null) Debug.WriteLine("Error no bus");
// Send messages on bus;
}
}
}
<MsmqTransportConfig InputQueue="test" ErrorQueue="error" NumberOfWorkerThreads="1" MaxRetries="5" />
<UnicastBusConfig>
<MessageEndpointMappings>
</MessageEndpointMappings>
</UnicastBusConfig>
Any ideas?
You have to specify IWantCustomInitialization on the endpoint config class. Otherwise NServiceBus won't call the Init() method. You also need to specify what serializer to use so add:
Configure.With()
.StructureMapBuilder()
.XmlSerializer();
Hope this helps!
Related
I have a problem with Symfony DependencyInjection Component. I want to inject interfaces into controllers, so I could only use interface methods. But, I notice I can use any public method from class that implement the interface and this is wrong. I follow the great article: http://php-and-symfony.matthiasnoback.nl/2014/05/inject-a-repository-instead-of-an-entity-manager/
Write the test service class and interface
interface ITestService
{
public function interfaceFunction();
}
class TestService implements ITestService
{
public function interfaceFunction() {/* do somenthing */}
public function classFunction() {/*do somenthing*/}
}
Configure my application service class as a service (test_service)
# file: app/config/services.yml
test_service:
class: MyApp\Application\Services\TestService
Configure my controller as a service:
# file: app/config/services.yml
test_controller:
class: MyApp\AppBundle\Controller\TestController
arguments:
- '#test_service'
Using service in controller
class TestController extends Controller
{
private testService;
function _construct(ITestService $testService)
{
$this->testService = $testService;
}
public function indexAction()
{
// This should be inaccesible but it works :(
$this->testService->classFunction();
// This is the only function I should use.
$this->testService->interfaceFunction();
}
As #Timurib says, this is because despite having Type Hintings, PHP doesn't evaluate the methods to call until runtime. This could be seen as something undesirable, but it allows to use some technics such as Duck Typing.
Here you have a simplified example based on the one you're providing (it doesn't put the Symfony Container into the mix, because this is something purely related to PHP). You can run it on 3v4l.org:
interface IService
{
public function interfaceFunction();
}
final class ServiceWithOtherFunction implements IService
{
public function interfaceFunction() { echo "ServiceWithOtherFunction interfaceFunction\n"; }
public function otherFunction() { echo "ServiceWithOtherFunction otherFunction\n"; }
}
final class Controller
{
private $service;
public function __construct(IService $service)
{
$this->service = $service;
}
public function indexAction()
{
$this->service->interfaceFunction();
$this->service->otherFunction();
}
}
$controllerWithOtherFunction = new Controller(new ServiceWithOtherFunction);
$controllerWithOtherFunction->indexAction();
Output:
ServiceWithOtherFunction interfaceFunction
ServiceWithOtherFunction otherFunction
But when we inject another implementation that does not contains the otherFunction, the code throws an Error at runtime:
final class ServiceWithoutOtherFunction implements IService
{
public function interfaceFunction() { echo "ServiceWithoutOtherFunction interfaceFunction\n"; }
}
$controllerWithoutOtherFunction = new Controller(new ServiceWithoutOtherFunction);
$controllerWithoutOtherFunction->indexAction();
Output:
ServiceWithoutOtherFunction interfaceFunction
Fatal error: Uncaught Error: Call to undefined method ServiceWithoutOtherFunction::otherFunction() in /in/mZcRq:28
Stack trace:
#0 /in/mZcRq(43): Controller->indexAction()
#1 {main}
thrown in /in/mZcRq on line 28
Process exited with code 255.
If you're going towards the use of interfaces, DI, and DIC, you should not call any public method rather than the exposed by the interface. This is the only way to really take advantadge of the benefits of having an interface: Decoupling from the implementation details, and be able to change the class to be injected without changing anything inside your Controller.
I have implement simple EJB 3.0 deployed it on weblogic 12c. The EJB contains a reference to a different EJB as a member declared as a reference of implemented local interface with annotation #EJB. When I invoke a method of the encapsulated EJB I get a null pointer exception. The same does not happen when I inject session context or data source using #SessionContext or #Resource respectivley. What I want to understand is do I have to define a reference in
in weblogic.xml for linking two EJBs. Is this same for all production grade application servers like jboss, websphere or Tomcat EE.
Here is more details about code & deployment:
#Remote
public interface MyEjbRemote1 {
abstract public void func1();
}
#Stateless
public class MyEJB1 implements MyEjbRemote1 {
public void func1() {}
}
#Remote
public interface MyEjbRemote {
abstract public void func();
}
#Stateless
public class MyEjb implements MyEjbRemote, MyEjbLocal {
#EJB
MyEjbRemote1 ejb1;
#Resource
SessionContext sessionContext;
public void func() {
ejb1.func1();
}
public void func1() {
System.out.println("Local interface call for EJB");
}
}
The call to func1 method using remote interface is throwing a null pointer exception.
I have not put any details in ejb-jar.xml, weblogic-ejb-jar.xml or weblogic.xml. My question is what addition details is required.
Please forgive my ignorance, but I am very new to IOC and NinJect. I have searched for high and low for easily understandable solutions but so far they have eluded me.
So far I have the following and all works as expected:
private class StandardModule : NinjectModule
{
public override void Load()
{
Bind<ILog>().To<NLogLogger>(); // Use NLog
Bind<IMyEntityFrameWorkRepository().To<MyEntityFrameWorkRepository>();
}
}
MyEntityFrameWorkRepository then creates its own EF DbContext via a connection string declared in app/web.config:
public class MyDbContext : DbContext
{
public MyDbContext() : base("MyAppConfig")
{
}
........
}
HOWEVER!! My goal is something like this - I realise this syntax is "nonsense" (and I think I may have to IOC MyDbConext too) , but I hope the "pseudo-code" conveys my desire:
private class StandardModule : NinjectModule
{
public override void Load()
{
Bind<ILog>().To<NLogLogger>(); // Use NLog
string mySqlConnectionString = MyApp.GetCommandLineArgument("sqlconn"); // "Data Source=..."
Bind<IMyEntityFrameWorkRepository().To<MyEntityFrameWorkRepository>(mySqlConnectionString);
}
}
.................
public class MyDbContext : DbContext
{
public MyDbContext( string sqlConnectionString) :
base(sqlConnectionString) // will accept a standard SQL connection string
{
}
........
}
I would truly appreciate some feedback from IOC / NinJect experts, since I am sure any "pattern" can be very useful in other scenarios.
You can use the .WithConstructorArgument() method to specify constructor arguments. The first argument should be the name of the constructor parameter.
public class StandardModule : NinjectModule
{
public override void Load()
{
string connectionString = "...";
Bind<IMyEntityFrameWorkRepository().To<MyEntityFrameWorkRepository>()
.WithConstructorArgument("sqlConnectionString", connectionString);
}
}
Newer versions of Ninject allow to get rid of magic strings in the binding definition. Something like this:
public class StandardModule : NinjectModule
{
public override void Load()
{
string connectionString = "...";
Bind<IMyEntityFrameWorkRepository()
.ToConstructor(_ => new MyEntityFrameWorkRepository(connectionString);
}
}
For bindings involving generic types (e.g. bind ISomeService<T> to SomeService<T> and binding should be performed for all possible types at once), ToConstructor cannot be used (a new expression is required), so WithConstructorArgument remains the simplest approach. E.g.:
Bind(typeof(ISomeService<>))
.To(typeof(SomeService<>))
.WithConstructorArgument("someParam", "someValue");
I can do this in Castle Windsor:
public abstract class AbstractFactory
{
protected AbstractFactory(Foo constructorParm)
{
// Do something with parameter...
}
}
public class DescendentFactory : AbstractFactory
{
public DescendentFactory(Foo constructorParm) : base(constructorParm)
{
}
}
// The container is configured via XML, the service AbstractFactory and the
// type DescendentFactory
container.Resolve<AbstractFactory>("DescendentFactoryId", new { constructorParm = injectedValue });
Is this possible in Unity? I've tried doing it but it complains that it can't find the constructor. It seems I can only inject via the sub-type.
You can only inject via the sub-type. It needs a public constructor.
I'm new to IoC/DI frameworks. The first one I am trying is the Ninject framework. It seems straightforward, but I can't get my console application to run. I keep getting an ActivationException stating:
"Error activating MainWindow: the StandardProvider returned an instance of type FutureRealisticDateManager, which is not compatible with the requested service.
Using default binding from MainWindow to FutureRealisticDateManager (via StandardProvider)
declared by DateBindingModule.Load()
Activation path:
1) active request for MainWindow
from Program.Main()
using default binding from MainWindow to FutureRealisticDateManager (via StandardProvider)
declared by DateBindingModule.Load()"
My code is very simple. Here is my Program file...
class Program
{
static void Main(string[] args)
{
IKernel k = new StandardKernel(new DateBindingModule());
MainWindow mw = k.Get<MainWindow>();
mw.Show();
Console.ReadLine();
}
}
Here is my ninject binding module...
public class DateBindingModule : StandardModule
{
public override void Load()
{
Bind<MainWindow>().To<FutureRealisticDateManager>();
}
}
Here is the class that receives the injected class...
class MainWindow
{
private IRealisticDateManager _d;
[Inject]
public MainWindow(IRealisticDateManager dateManager)
{
_d = dateManager;
}
public void Show()
{
Console.WriteLine("*** MainWindow [" + _d.GetRealisticDate().ToString() + "] ");
}
}
And here is the actual class being injected...
public class FutureRealisticDateManager : TestNinject.IRealisticDateManager
{
public DateTime GetRealisticDate()
{
return DateTime.Now.AddDays(15);
}
}
And finally the simple interface that the injected class should implement...
public interface IRealisticDateManager
{
DateTime GetRealisticDate();
}
Can anybody see what I am doing wrong?
It fails because your binding is not right:
Bind<MainWindow>().To<FutureRealisticDateManager>();
FutureRealisticDataManager does not inherit from MainWindow.
Instead you should write:
Bind<IRealisticDateManager>().To<FutureRealisticDateManager>();
This tells Ninject to return FutureRealisicDateManager whenever IRealisicDateManager is requested.
This way when you call k.Get<MainWindow>() kernel will inject FutureRealisticDateManager to the constructor.