I have the following constructor
#Inject
public MyClass(Provider<TestClass> testProvider, #Named("myName") String name) {
//constructor stuff
}
My module:
#Provides
#Named("myName")
public String getName(SomeObject object) {
return object.getName();
}
The problem is that Guice doesn't do the binding.
Now if I remove the #Named annotation, it works. The getName() method is succesfully called. When adding the #Named annotation though, getName() is never called, and my constructor ends up being injected with an empty string.
Only one of my methods annotated with#Provides returns a String, but I'd still like to name it since String is a pretty common object that could be injected.
I have also tried the binding within the configure() method (as per the documentation, but still nothing.
Anyone know what I'm missing? I checked the documentation to no avail.
EDIT: I'm sure that my imports are correct
Works for me. Here is the code I used to verify (guice 4.0):
package guice;
import com.google.inject.*;
import com.google.inject.name.Named;
public class Main {
public static void main(String[] args) {
Guice.createInjector(new MyModule()).getInstance(MyClass.class);
}
}
class MyClass {
#Inject
public MyClass(Provider<TestClass> testProvider, #Named("myName") String name) {
System.out.println(name);
}
}
class MyModule extends AbstractModule {
#Override
protected void configure() {
}
#Provides
#Named("myName")
public String getName(SomeObject object) {
return object.getName();
}
}
class SomeObject {
public String getName() {
return "helloWorld";
}
}
class TestClass {
}
Prints "helloWorld" as expected.
Related
I have an Enum :
public enum MyEnum {
INSTANCE;
#Autowired
Regroupements regroupements;
#PostConstruct
public void initi()
{
System.out.println("---------- i am not called!");
}
private MyEnum() {
System.out.println("---------- i am called!");
}
}
And a Spring-Factory
#Component
public class MyEnumFactory implements FactoryBean<MyEnum>{
#Override
public MyEnum getObject() throws Exception {
return MyEnum.INSTANCE;
}
#Override
public Class<?> getObjectType() {
return MyEnum.class;
}
#Override
public boolean isSingleton() {
return true;
}
}
The problem is :
when in call the method of the factory to give me the unique INSTANCE,
the init() method is never called!
you'll notice that, as it is an Enum, the class don't have #Component
annotation. it's why I use a factory.
what I want is to launch a post-construct, it doesn't matter the way.
You can't use enum as bean (and normally you don't have to), so you can neither use #PostConstruct on it, nor even autowire anything inside: your dependency Regroupements regroupements; is going to be null.
Here's my code:
// Groovy
interface MyMapper {
Buzz toBuzz(Fizz fizz);
}
class MyMapperImpl implements MyMapper {
#Named("SIMPLE_FOOBAR")
Foobar foobar;
MyMapperImpl(Foobar foobar) {
super();
this.foobar = foobar;
}
#Override
Buzz toBuzz(Fizz fizz) {
// ...etc.
}
}
class Whistlefeather {
MyMapper mapper;
Whistlefeather(MyMapper mapper) {
super();
this.mapper = mapper;
}
void doSomething(Fink fink) {
Fizz fizz = getSomehow(fink);
Buzz buzz = mapper.toBuzz(fizz);
// Do something with 'buzz'...
}
}
class ApplicationMain {
Whistlefeather whistlefeather;
#Inject
ApplicationMain(Whistlefeather whistlefeather) {
super();
this.whistlefeather = whistlefeather;
}
static void main(String[] args) {
Injector injector = Guice.createInjector(new ApplicationModule());
ApplicationMain appMain = injector.getInstance(ApplicationMain);
appMain.run();
}
void run() {
whistlefeather.doSomething(new Fink());
}
}
Here's my Guice module:
class ApplicationModule extends AbstractModule {
#Override
protected void configure() {
// I have to name the Foobars because in reality there will be
// *many* of them, each configured slightly different.
bind(Foobar.class).annotatedWith(Names.named("SIMPLE_FOOBAR"))
.toInstance(new Foobar(true, true, false, 103, "yee haw"));
bind(MyMapper.class).to(MyMapperImpl);
}
}
Here's my exception:
Could not find a suitable constructor in com.me.myapp.MyMapperImpl.
Classes must have either one (and only one) constructor annotated
with #Inject or a zero-argument constructor that is not private.
My understanding was that I only need to annotate constructors with #Inject if I would be directly calling them through the Injector#getInstance(...) method. Since I do this with ApplicationMain, which contains a reference to Whistlefeather, which contains a reference to MyMapper, I didn't think I would have to annotate the MyMapperImpl constructor.
Any ideas as to where I'm going awry here?
In order for Guice to create any object, it has to know which constructor to use. This is true all the way down the Object Graph.
Consider the following code:
public interface Something { }
public class SomethingImpl implements Something {
private final String data;
public SomethingImpl(String data) {
this.data = data;
}
public SomethingImpl(Integer data) {
this.data = data.toString();
}
}
public class AnotherClass {
private final Something something;
#Inject
public AnotherClass(Something something) {
this.something = something;
}
}
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Something.class).to(SomethingImpl.class);
bind(String.class).toInstance("Hello!");
bind(Integer.class).toInstance(50);
}
}
In this scenario, how is Guice supposed to know which constructor to use in SomethingImpl? If you were the author of Guice, how would you write it?
Obviously, you can't answer, because it's impossible. There has to be some sort of mechanism to tell Guice which constructor to use, regardless of whether or not it's called by Injector.getInstance() or not; that's why you have to annotate at least one constructor. Guice will use a no-argument constructor by default if one is specified, but if there isn't one, Guice doesn't know what to do.
I've an EJB as follows:
public class Bar() {
private String s;
public Bar() {
this.s = "bar";
}
#Inject public Bar(String s) {
this.s = s;
}
}
How can I inject that bean by using the arg-constructor into another Foo class?
Then, I define the Foo class as EJB, with the aim to perform the DI for it into another class (for instance, a WebServlet). How can I inject a Foo class instance by passing a String to properly set up Bar arg-constructor as inner-dependency?
Is there a better way to define Bar in order to achieve points above?
The annotated constructor injection tells CDI that whenever someone requests an instance of Bar to be injected, it should use the constructor marked with #Inject.
The CDI container then tries to get instances for all required constructor parameters and fails, because it can not deal with "String". It just doesn't know which String you mean.
You have to help the container resolving the dependency by using a Producer and a Qualifier to tell him what String you want. I just give you the simplest possible solution here:
public class Bar {
#Inject
public Bar(#Named("myString") String s) {
this.s = s;
}
}
And then another class (doesn't have to be an different class, but its much more readable):
public class MyStringProducer {
#Produces
#Named("myString")
public String getMyString() {
return ...; // whatever you want ... read JSON, parse properties, randomize ...
}
}
#Inject only works when you are injecting "managed" objects. String is not a managed object, thus this won;t work.
However, the following example should work (I have used spring here. Use the DI initializaton code according to the library you are using):
#Named
public class Foo {
#Inject
Bar bar;
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext("com.pkg1");
Foo foo = (Foo)ctx.getBean("foo");
System.out.println(foo.bar.getString());
}
}
#Named
public class Bar {
private String s;
public Bar() {
this.s = "bar";
}
#Inject
public Bar(Bar1 bar1) {
this.s = bar1.getS();
}
public String getString() {
return s;
}
}
#Named
class Bar1 {
private String s="bar1";
public String getS() {
return s;
}
}
I am attempting to figure out how to use a custom annotation and HK2 to inject something into a Resource method. Because I'm in a Spring webapp environment, I just piled on the existing helloworld-spring-webapp Jersey 2 example. My problem is, is the Resource method is called twice. The first time, the injection happens successfully, the second time, it does not.
InjectionResolver.resolve() method
#Override
public Object resolve(Injectee injectee, ServiceHandle<?> root) {
return "THIS HAS BEEN INJECTED APPROPRIATELY";
}
Binder.configure() method
#Override
protected void configure() {
bind(SampleInjectionResolver.class).to(new TypeLiteral<InjectionResolver<SampleParam>>() {}).in(Singleton.class);
}
ResourceConfig registering of binder
public MyApplication () {
register(new SampleInjectionResolver.Binder());
...
JerseyResource.getHello()
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getHello(#SampleParam String inject) {
System.err.println("EXECUTING!");
System.err.println("*******************************INJECTED: " + inject);
return inject;
}
Server output from a SINGLE call
EXECUTING!
*******************************INJECTED: THIS HAS BEEN INJECTED APPROPRIATELY
EXECUTING!
*******************************INJECTED:
Have I missed a configuration somewhere? I can't figure out why it's being called twice. I'm assuming if I fix that, the issue of the InjectionResolver not working on the 2nd call will be a non-issue.
I faced with the exactly same issue - Twice call of the annotated resource method.
After deep investigation, I have found the way, how to use custom annotation in the Jersey 2.x.
Custom annotation class (TestMessage.java):
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.PARAMETER })
public #interface TestMessage {}
Custom annotation resolver (TestMessageResolver.java):
public class TestMessageResolver {
// InjectionResolver implementation
public static class TestMessageInjectionResolver extends ParamInjectionResolver<TestMessage> {
public TestMessageInjectionResolver() {
super(TestMessageValueFactoryProvider.class);
}
}
// ValueFactoryProvider implementation
#Singleton
public static class TestMessageValueFactoryProvider extends AbstractValueFactoryProvider {
#Inject
public TestMessageValueFactoryProvider(MultivaluedParameterExtractorProvider mpep, ServiceLocator injector) {
super(mpep, injector, Parameter.Source.UNKNOWN);
}
#Override
protected Factory<?> createValueFactory(Parameter parameter) {
Class<?> classType = parameter.getRawType();
if (classType == null || (!classType.equals(String.class))) {
return null;
}
return new AbstractContainerRequestValueFactory<String>() {
#Override
public String provide() {
return "testString";
}
};
}
}
// Binder implementation
public static class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(TestMessageValueFactoryProvider.class).
to(ValueFactoryProvider.class).
in(Singleton.class);
bind(TestMessageInjectionResolver.class).
to(new TypeLiteral<InjectionResolver<TestMessage>>(){}).
in(Singleton.class);
}
}
}
Custom annotation usage (JerseyResource.java):
#Path("jersey")
public class JerseyResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getMethod(#TestMessage String message) {
return "getMethod(), message=" + message;
}
}
Resolver registration(SpringJerseyApplication.java):
public class SpringJerseyApplication extends ResourceConfig {
public SpringJerseyApplication() {
register(JerseyResource.class);
register(new TestMessageResolver.Binder());
}
}
Hope it will be helpful :)
I would like a JUnit 4 test class to implement the same interface as the class its testing. This way, as the interface changes (and it will, we're in early development), the compiler guarantees that corresponding methods are added to the test class. For example:
public interface Service {
public String getFoo();
public String getBar();
}
public class ServiceImpl implements Service {
#Override public String getFoo() { return "FOO"; }
#Override public String getBar() { return "BAR"; }
}
public class ServiceTest implements Service {
#Override
#Test
public String getFoo() {
//test stuff
}
#Override
#Test
public String getBar() {
//test stuff
}
}
When I try this, I get an error: "java.lang.Exception: Method getFoo() should be void",
presumably because test methods must return void. Anybody know of any way around this?
I have to admit, it is a neat trick, though it doesn't scale well to multiple test scenarios.
Anyways, you can use custom runner. For example:
#RunWith(CustomRunner.class)
public class AppTest {
#Test
public int testApp() {
return 0;
}
}
public class CustomRunner extends JUnit4ClassRunner {
public CustomRunner(Class<?> klass) throws InitializationError {
super(klass);
}
protected void validate() throws InitializationError {
// ignore
}
}
A more natural way would probably be to use a code coverage tool, such as Cobertura. It integrates with JUnit nicely AND it shows you cases where your tests may be deficient in some cases (there are many cases such a tool won't catch though).