How to get plugins by setting a path - mef

I created console c# project. and in the code I have made a module. My code looks like this.
[Import]
public IMessageSender MessageSender { get; set; }
public static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
public void Run()
{
Compose();
Console.ReadLine(MessageSender.Send("Message Sent"));
}
private void Compose()
{
AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
public interface IMessageSender
{
string Send(string message);
}
[Export(typeof(IMessageSender))]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
return message;
}
}
It works perfectly fine. But now I added a new project in my solution and added module into that
AnotherProject->EmailSender.cs
[Export(typeof(IMessageSender))]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
return message;
}
}
Now in the main console program I changed some of my code.
private void Compose()
{
var catalog = new DirectoryCatalog(path);
//AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
But now when I run this program. It doesnt load the module. MessageSender in main program is null. What wrong I have done.

There are a few things you need to check:
Have you correctly referenced the assemblies?
The DirectoryCatalog by default uses the search pattern *.dll. Because you have a console application, which uses the .exe extension, no exports in that assembly will get picked up by the DirectoryCatalog - with the default search pattern. You'll likely want to use an AggregateCatalog, passing in the DirectoryCatalog (*.dll), and either another DirectoryCatalog (*.exe), or an AssemblyCatalog, of the entry assembly.
You currently have one [Import] where you may end up with multiple [Export(typeof(IMessageSender))], you didn't state that you have moved the EmailSender to the class library, merely that you have created a new one, which means you'll likely end up with a cardinality mismatch where it is expecting a sinple import, you have many exports. This will explicitly throw an exception, which is what will happen even it couldn't find a single instance of IMessageSender, because your [Import] attribute is not set to allow a default value where no part can be provided. If you need to be fault tollerant, you can use [Import(AllowDefault = true)]
Incidentally... the above code won't compile, I assume it was just an example and not a copy-paste from your current code?
public void SendMessage(string message)
{
return message;
}
You're retuning a message to a void method - that can't be done, and it also means that EmailSender doesn't correctly implement IMessageSender. Not too bothered, as I think it is an example more than actual code.

Related

Way to find all affected locations by variable

I want to find code lines, where a certain property can get.
Consider I have property holder class and in java editor look to some setter method. In code is property readed and setted to entity. And before save to database, do validation on server side. So I want see from client.propertyHolder.setter to server.entityValidator.getter
Simple example
public class Main{
public static void main(String[] args) {
Holder h = new Holder();
h.setHolder("Something"); // Here i want use plugin
Entity e = new Entity();
e.setName(h.getHolder());
// Consider this is on server side in validator and call only if annotation validation is OK
Assert.assertTrue(e.getName().length() > 0)
}
}
public class Holder{
public String holder = null;
public void setHolder(String holder){this.holder = holder}
public void getHolder(){return holder}
}
public class Entity{
#javax.validation.constraints.NotNull
private String name = null;
public void setName(String name){this.name = name}
public void getName(){return name}
}
So i should get lines
e.setName(h.getHolder());
Assert.assertTrue(e.getName().length() > 0)
and be nice if NotNull anotations too
Is there a way, how to achive this? Some good free eclipse-plugin maybye?
Thanks for help. Pavel

NullPointerException when I changed all my methods to static

Using Selenium w Java and Test NG (POM format) Switched everything from not static to static and changed everything accordingly, getting NullPointerException. It worked when everything was not static, but making everything static requires less code so I'd prefer to have it that way.
Here is my code.. while trying to paste my code for some reason it did not recognize the import statements as code so I just did not include them, but rest assured everything has been imported that is needed! :)
Package pages;
public class locationPage {
WebDriver driver;
static #FindBy (id="btn_bogota") WebElement chooseBogota;
static #FindBy (id="btn_medellin") WebElement chooseMedellin;
static #FindBy (xpath="//title") WebElement pageTitle;
public locationPage (WebDriver driver){
this.driver=driver;
PageFactory.initElements(driver, this);
}
public static void chooseLocation (String location) {
if (location.equals("Bogota"))
{
chooseBogota.click();
}
else if (location.equals("Medellin")){
chooseMedellin.click();
}
}
}
Package testcases;
public class selectLocation {
WebDriver driver;
#BeforeClass
public void setup() throws InterruptedException{
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://dev01.juanregala.com.co/");
//Generating Alert Using Javascript Executor
JavascriptExecutor javascript = (JavascriptExecutor) driver;
javascript.executeScript("alert('Select Location');");
Thread.sleep(2000);
driver.switchTo().alert().accept();
}
#AfterTest
public void quit(){
driver.quit();
}
#Test (priority=0)
public void location(){
locationPage.chooseLocation("Medellin");
}
}
It keeps giving me a NullPointerException referring to
chooseMedellin.click();
and
locationPage.chooseLocation("Medellin");
I am not really sure how else to describe my issue :( Please help!
You are getting a NullPointerException because the fields are not initialized. You can't use a page object in this way. Even if you could, you probably wouldn't want to since a page object is tied to a particular web driver and that would mean you could never use the same page object among multiple tests and run them in parallel.
Basically, the PageFactory only works on object instances. It won't initialize static fields and, even if it did, you are only calling the page factory from the constructor of your page and that is never being called since you only call a static method on that class.
You need to create an instance of the page object and then pass it to the PageFactory along with the driver that will be running the page object.
Simple example:
public class FooTest {
private WebDriver driver;
private FooPage page;
#BeforeMethod
public void setup() {
driver = new FirefoxDriver();
page = PageFactory.initElements(driver, FooPage.class);
}
#AfterMethod
public void tearDown() {
try {
driver.quit();
} catch ( Exception ignore ) { }
driver = null;
page = null;
}
#Test
public void testFoo() {
}
}
public class FooPage {
#FindBy(id="foo")
private WebElement fooElement;
public void clickFoo() {
fooElement.click();
}
}
Note the line:
page = PageFactory.initElements(driver, FooPage.class);
That method will actually call the default construct of FooPage. You can also instantiate the object yourself and pass it to the page factory like this:
page = new FooPage();
PageFactory.initElements(driver, page);

NInject simplest example doesn't work

I've got three projects:
UI
PluginManager
PluginOne
PluginTwo
Inside my Plugin Manager a create a simple plugin interface:
public interface IPlugin<T>
{
void sayMessage(T message);
T createMessage();
}
So, in my other projects I've two IPlugin implementation:
In porject PluginOneProject -->
-------------------------------
public class PluginOne : IPlugin<IntMessage>
{
public void sayMessage(IntMessage message)
{
System.Console.WriteLine(message.ToString());
}
}
where:
public class IntMessage
{
private int message;
public IntMessage(int message)
{
this.message = message;
}
public override string ToString()
{
return this.message.ToString();
}
}
In porject PluginTwoProject -->
-------------------------------
public class PluginTwo : IPlugin<StringMessage>
{
public void sayMessage(StringMessage message)
{
System.Console.WriteLine(message.ToString());
}
}
where:
public class StringMessage
{
private String message;
public StringMessage(String message)
{
this.message = message;
}
public override string ToString()
{
return this.message.ToString();
}
}
Obviously, I've added the corresponding project references.
So, in my UI porject I've NInject, and I perform this convention mapping:
kernel.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(IPlugin<>))
.BindAllInterfaces()
);
The graph is built correctly.
So, I don't know how to get an instance of PluginOne, or PluginTwo from UI project.
I'm trying to use this code, however, I've a problem with generic interfaces...
foreach (IPlugin<?> plugin in kernel.GetAll(typeof(IPlugin<>)))
{
plugin.sayMessage(plugin.createMessage());
}
Unfortunately, you must request a specific interface from Ninject, so you must request either IPlugin<IntMessage> or IPlugin<StringMessage>.
I would suggest trying to refactor your app so that you can request a more generic interface, such as IPlugin, and/or create a message interface like IMessage that each message implements. It's not clear from your question what you're trying to accomplish.

Getting TinyIoc current container in a Nancy project

I'm building a small Nancy web project.
In a method of one of my classes (not a nancy module), I would like to basically do:
var myThing = TinyIoC.TinyIoCContainer.Current.Resolve<IMyThing>();
However, there is only one registration in .Current (non public members, _RegisteredTypes) which is:
TinyIoC.TinyIoCContainer.TypeRegistration
Naturally, in my above code, I'm getting:
Unable to resolve type: My.Namespace.IMyThing
So, I guess I'm not getting the same container registered in my bootstrapper?
Is there a way to get at it?
EDIT
To flesh out a bit more of what I'm trying to do:
Basically, my url structure looks something like:
/{myType}/{myMethod}
So, the idea being, going to: /customer/ShowAllWithTheNameAlex would load the Customer service, and execute the showAllWithTheNameAlex method
How I do this is:
public interface IService
{
void DoSomething();
IEnumerable<string> GetSomeThings();
}
I then have an abstract base class, with a method GetService that returns the service.
It's here that i'm trying to use the TinyIoC.TinyIoCContainer.Current.Resolve();
In this case, it would be TinyIoC.TinyIoCContainer.Current.Resolve("typeName");
public abstract class Service : IService
{
abstract void DoSomething();
abstract IEnumerable<string> GetSomeThings();
public static IService GetService(string type)
{
//currently, i'm doing this with reflection....
}
}
Here's my implementation of the service.
public class CustomerService : Service
{
public void DoSomething()
{
//do stuff
}
public IEnumerable<string> GetSomeThings()
{
//return stuff
}
public IEnumerable<Customer> ShowAllWithTheNameAlex()
{
//return
}
}
Finally, I have my Nancy Module, that looks like:
public class MyModule : NancyModule
{
public MyModule()
{
Get["/{typeName}/{methodName}"] = p => ExecuteMethod(p.typeName, p.methodName);
}
private dynamic ExecuteMethod(string typeName, string methodName)
{
var service = Service.GetService(typeName);
var result = service.GetType().GetMethod(methodName).Invoke(service, null);
//do stuff
return result; //or whatever
}
}
#alexjamesbrown - The short answer is, you don't. Nancy was specifically designed so that you did not deal with the container directly. You mention that the class, that you want to take a dependency on IMyThing, is not a NancyModule. Well this is not an issue, as long as one of your modules has a reference to it, then those dependencies can also have their own dependencies that will be satisfied at runtime.
public interface IGreetingMessageService
{
string GetMessage();
}
public class GreetingMessageService: IGreetingMessageService
{
public string GetMessage()
{
return "Hi!";
}
}
public interface IGreeter
{
string Greet();
}
public class Greeter
{
private readonly IGreetingMessageService service;
public Greeter(IGreetingMessageService service)
{
this.service = service;
}
public string Greet()
{
return this.service.GetMessage();
}
}
public class GreetingsModule : NancyModule
{
public GreetingModule(IGreeter greeter)
{
Get["/"] = x => greeter.Greet();
}
}
The above will work just fine and Greeter will have it's dependency on IGreetingMessageService satisfied at runtime
I have had a very similar issue, needing to "share" the container. The reason this is an issue is that my program runs as a service using Nancy self hosting to provide a REST API. My modules have dependencies which are injected by Nancy itself, but the other parts of the app which are not referenced from modules also need dependencies injected.
Multiple containers are not a sensible option here (or anywhere really), I need to share the container between Nancy and the rest of the app.
I simply did the following
(I'm using Autofac but I suspect that TinyIoC in similar)
public class Bootstrapper : AutofacNancyBootstrapper
{
private static readonly Lazy<ILifetimeScope> container = new Lazy<ILifetimeScope>(RegisterTypes);
public static ILifetimeScope Container => container.Value;
protected override ILifetimeScope GetApplicationContainer()
{
return container.Value;
}
// Create container and register my types
private static ILifetimeScope RegisterTypes()
{
var builder = new ContainerBuilder();
// Register all my own types.....
return builder.Build();
}
}
Then, in my main code, I can use the container myself
public class Program
{
public static void Main(string[] args)
{
// Resolve main service with all its dependencies
var service = Bootstrapper.Container.Resolve<Service>();
service.Run();
}
}
As my NancyHost is within the Service, the container is constructed (once) upon its first use in main, this static is then used when Nancy gets round to creating the Bootstrapper itself.
In an ideal world, I wouldn't really want a globally accessible container, normally it would be local to the main function.
In this particular case "not dealing with the container directly" is highly problematic:
public interface IFoo {}
public class Foo : IFoo { public Foo(string bar) {} }
Assume IFoo already is a constructor dependency of a Nancy module.
Note the Foo constructor's string dependency. I need to communicate to the container to use that constructor for an IFoo singleton, when encountered as a Nancy module dependency. I need to register that on the TinyIoC instance NancyFx uses, and pass in the actual value of bar.

how to generate deployment descriptor using ejbGen for weblogic?

I was reading the tutorial on this page:
http://edocs.bea.com/docs/cd/E13222_01/wls/docs81/medrec_tutorials/ejbgen.html#858279
And I have the following file BankAccountEJB.java
import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
public abstract class BankAccountEJB implements EntityBean {
private EntityContext context;
public void setEntityContext(EntityContext aContext) {
context = aContext;
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void ejbRemove() {
}
public void unsetEntityContext() {
context = null;
}
public void ejbLoad() {
}
public void ejbStore() {
}
public abstract String getName();
public abstract void setName(String name);
public abstract Float getBalance();
public abstract void setBalance(Float balance);
public java.lang.Long ejbCreate(String name, Float balance) throws CreateException {
if (name == null) {
throw new CreateException("The field \"key\" must not be null");
}
// TODO add additional validation code, throw CreateException if data is not valid
setName(name);
setBalance(balance);
return null;
}
public void ejbPostCreate(java.lang.Long key) {
// TODO populate relationships here if appropriate
}
}
and I run java weblogic.tools.ejbgen.EJBGen -ddOnlyGen BankAccountEJB.java which produces the following error:
Exception in thread "main" com.bea.wls.ejbgen.EJBGenException: ejbName is a required attribute
at com.bea.wls.ejbgen.Bean.createBeanSpecificTags(Bean.java:202)
at com.bea.wls.ejbgen.Bean.(Bean.java:127)
at com.bea.wls.ejbgen.EntityBean.(EntityBean.java:76)
at com.bea.wls.ejbgen.EJBFactory.createBean(EJBFactory.java:135)
at com.bea.wls.ejbgen.EJBFactory.createBean(EJBFactory.java:99)
at com.bea.wls.ejbgen.EJBGenSGen.initModule(EJBGenSGen.java:106)
at com.bea.sgen.SGen.run(SGen.java:205)
at com.bea.wls.ejbgen.EJBGen.main(EJBGen.java:212)
at com.bea.wls.ejbgen.EJBGen.main(EJBGen.java:238)
at weblogic.tools.ejbgen.EJBGen.main(EJBGen.java:21)
Any input will be greatly appreciated~!
Note: Are you still running Weblogic 8.1 - it's already reached end of life. Also ejbgen works with EJB 2.x and over the last 2 years, development has moved on to EJB 3, so i'd advise you to catch up on those.
Now to your specific problem.
Your code does not seem to have the required annotations for ejbgen to work.
Annotations like this which are used in generation of the descriptors.
* #ejbgen:entity
* ejb-name = containerManaged
* table-name = ejbAccounts
* data-source-name = examples-dataSource-demoPool
* prim-key-class = AccountPK
* invalidation-target = ServiceDesignEJB
As your URL says the code in the tutorial has the right data as a sample - make sure you replicate those correctly in your own code.
EJBGen uses annotations in the bean
file to generate the deployment
descriptor files and the EJB Java
source files. EJB files in the MedRec
application are already annotated for
EJBGen.
For another version of ejbgen, see http://www.beust.com/ejbgen/