If I remove the generic Type Parameters of the IService Dependency
then everything works as expected.
Here is the example:
Our generic Service Interface:
[java]
package de.tutorials.services;
/**
* @author Thomas.Darimont
*/
public interface IService<TRequest extends IRequest, TResponse extends
IResponse> {
TResponse process(TRequest request);
}
[/java]
IRequest:
[java]
package de.tutorials.services;
/**
* @author Thomas.Darimont
*/
public interface IRequest {
String getData();
void setData(String data);
}
[/java]
IResponse:
[java]
package de.tutorials.services;
public interface IResponse {
String getResult();
void setResult(String result);
}
[/java]
Concrete MockService Implementation:
[java]
/**
*
*/
package de.tutorials.services.internal.mock;
import com.google.inject.Singleton;
import de.tutorials.services.IService;
/**
* @author Thomas.Darimont
*
*/
@Singleton
public class MockService implements IService<MockRequest,
MockResponse> {
public MockResponse process(MockRequest request) {
MockResponse response = new MockResponse();
response.setResult(request.getData().toUpperCase());
return response;
}
}
[/java]
The MockRequest:
[java]
package de.tutorials.services.internal.mock;
import de.tutorials.services.IRequest;
/**
* @author Thomas.Darimont
*/
public class MockRequest implements IRequest {
String data;
/**
* @return the data
*/
public String getData() {
return data;
}
/**
* @param data the data to set
*/
public void setData(String data) {
this.data = data;
}
}
[/java]
The MockResponse:
[java]
package de.tutorials.services.internal.mock;
import de.tutorials.services.IResponse;
/**
* @author Thomas.Darimont
*/
public class MockResponse implements IResponse {
String result;
/**
* @return the result
*/
public String getResult() {
return result;
}
/**
* @param result the result to set
*/
public void setResult(String result) {
this.result = result;
}
}
[/java]
The MainModule:
[java]
package de.tutorials;
import com.google.inject.Binder;
import com.google.inject.Module;
import de.tutorials.services.IService;
import de.tutorials.services.internal.mock.MockService;
/**
* @author Thomas.Darimont
*/
public class MainModule implements Module {
public void configure(Binder binder) {
binder.bind(IService.class).to(MockService.class);
}
}
[/java]
Our Client:
[java]
/**
*
*/
package de.tutorials;
import com.google.inject.Inject;
import de.tutorials.services.IRequest;
import de.tutorials.services.IResponse;
import de.tutorials.services.IService;
import de.tutorials.services.internal.mock.MockRequest;
/**
* @author Thomas.Darimont
*
*/
public class Client {
IService<IRequest, IResponse> service;
/**
* @return the service
*/
public IService<IRequest, IResponse> getService() {
return service;
}
/**
* @param service
* the service to set
*/
@Inject
public void setService(IService<IRequest, IResponse> service) {
System.out.println("setService");
this.service = service;
}
public void start() {
IRequest request = new MockRequest();
request.setData("bubu");
IResponse response = getService().process(request);
System.out.println(response.getResult());
}
}
[/java]
Here is the Main Class:
[java]
package de.tutorials;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* @author Thomas.Darimont
*/
public class Main {
/**
* @param args
*/
/**
* @param args
*/
public static void main(String[] args) {
// Bootstrap Guice Runtime
Injector injector = Guice.createInjector(new MainModule());
System.out.println(injector);
// Start Client
injector.getInstance(Client.class).start();
}
}
[/java]
Did I miss something?
Best regards,
Thomas
If I try to inject a Service Implementation into a generic service
Property I get this exception:
Exception in thread "main" com.google.inject.ConfigurationException:
Error at de.tutorials.Client.setService (Client.java:35) Binding to
de.tutorials.services.IService<de.tutorials.services.IRequest,
de.tutorials.services.IResponse> not found. No bindings to that type
were found.
at com.google.inject.BinderImpl
$RuntimeErrorHandler.handle(BinderImpl.java:426)
at
com.google.inject.AbstractErrorHandler.handle(AbstractErrorHandler.java:
30)
at
com.google.inject.ErrorMessages.handleMissingBinding(ErrorMessages.java :
46)
at com.google.inject.InjectorImpl
$MissingDependencyException.handle(InjectorImpl.java:791)
at
com.google.inject.InjectorImpl.addInjectorsForMembers(InjectorImpl.java:
389)
at
com.google.inject.InjectorImpl.addSingleInjectorsForMethods(InjectorImpl.java:
356)
at com.google.inject.InjectorImpl.addInjectors(InjectorImpl.java:351)
at com.google.inject.InjectorImpl$4.create (InjectorImpl.java:332)
at com.google.inject.InjectorImpl.getInstance (InjectorImpl.java:728)
thanks for the replys :)
I wonder whether we could make this work right know, because in this
case the generic information is available via reflection:
[java]
/**
*
*/
package de.tutorials;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* @author Tom
*
*/
public class GenericReflectionExample {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
Client client = new Client();
ParameterizedType parameterizedType = (ParameterizedType)
client.getClass().getDeclaredMethod("getService").getGenericReturnType();
Type[] types = parameterizedType.getActualTypeArguments();
System.out.println("ActualTypeArguments " + types[0] + ", " +
types[1]);
}
}
[/java]
Gives:
ActualTypeArguments interface de.tutorials.services.IRequest,
interface de.tutorials.services.IResponse
So if you know the actual type arguments, you should have enough
information to be able to wire the approriate generic dependencies, or
am I wrong?
For this Client (same as in the example above):
[java]
/**
*
*/
package de.tutorials;
import com.google.inject.Inject;
import de.tutorials.configuration.Configurable;
import de.tutorials.services.IRequest;
import de.tutorials.services.IResponse;
import de.tutorials.services.IService;
import de.tutorials.services.internal.mock.MockRequest;
/**
* @author Thomas.Darimont
*
*/
@Configurable
public class Client {
IService<IRequest, IResponse> service;
/**
* @return the service
*/
public IService<IRequest, IResponse> getService() {
return service;
}
/**
* @param service
* the service to set
*/
@Inject
public void setService(IService<IRequest, IResponse> service) {
System.out.println("setService");
this.service = service;
}
public void start() {
IRequest request = new MockRequest();
request.setData("bubu");
IResponse response = getService().process(request);
System.out.println(response.getResult());
}
}
[/java]
Best regards,
Thomas
--
Gregory Kick
http://kickstyle.net/
hmmm, have you already tried this TypeLiteral based solution?
binder.bind(new TypeLiteral<IService<IRequest, IResponse>>() {
}).to(MockService.class);
If I try this I get this compiler error:
The method to(Class<? extends IService<IRequest,IResponse>>) in the
type LinkedBindingBuilder<IService<IRequest,IResponse>> is not
applicable for the arguments (Class<MockService>)
de.tutorials.training.guice/src/de/tutorials MainModule.java
Best regards,
Thomas
args... shame one me I couldn't see the wood for the trees :) Thanx :D
Best regards
Thomas