Im trying to refactor my app to use play 2.4 dependency injection instead of cake pattern.
How do you inject a class with parameter, for example
class A(valX: Int) { } // How do you Inject val X ?
class B #Inject() (a : A)
Usually you wouldn't pass a parameter like an Integer in dependency injection - you'd use different ways to pass it on, like via a method parameter or a setter method. Via dependency injection you can inject only instances that are under control of your dependency injection system.
This is a simple example:
public class MyClass {
private int myParameterY;
private final MyOtherClass myInjectedInstance;
#Inject
ComponentResults(MyOtherClass injectedInstance) {
this.myInjectedInstance = injectedInstance;
}
// Pass myParameterX
public void myMethodThatNeedXAndY(int myParameterX) {
// Do something with myParameterX and myParameterY
}
// Use this setter to initialize myParameterY
public void setParameterY(int Y) {
this.myParameterY = Y;
}
}
Or if it is a constant you could use 'bind' in your Guice configuration.
bind(Integer.class).annotatedWith(Names.named("myParameterZ")).toInstance(1);
And then use this annotations to inject it:
#Named("myParameterZ")
Related
Currently I am trying to reduce the boilerplate in my java spring controllers by creating an interface CRUDRestController, which creates a common set of default endpoints:
interface CRUDRestController<T, Key extends Serializable> {
//...
String getEndpoint();
#RequestMapping(value = getEndpoint() + "/{key}", method = RequestMethod.GET)
default T get(#PathVariable("key") String key) {
return getRepository().findOne(stringToKey(key));
}
//...
}
The problem is that the above code does not compile since value = getEndpoint() + "/{key}" is supposedly not a compile time constant. In reality every controller's implementation of getEndpoint() is something like this:
#Override
public String getEndpoint() {
return "/clients";
}
This is clearly known at compile time, however I have no way of telling this to spring. Any ideas?
Maybe that will help you:
interface CRUDRestController<T, Key extends Serializable> {
#RequestMapping(value = "/{key}", method = RequestMethod.GET)
default T get(#PathVariable("key") String key) {
return getRepository().findOne(stringToKey(key));
}
}
and the implementation:
#RequestMapping("/clients")
public class ClientController implements CRUDRestController<Client, ClientKey> {
//...
}
This is a Java annotations restriction. All values passed to it must be compile time constants.
The value is clearly not known at compile time even if you would call a static method returning a static final.
I would like to know if it's possible to inject dependencies using Guice without having to pass by the routing.
If it is how can I call my class Test #Inject()... within my application ?
I think there are two ways to use Guice in Play framework:
1) Directly instantiate an object based on the binding:
Add Guice to your Build.scala app dependencies
val appDependencies = Seq(
"com.google.inject" % "guice" % "3.0"
)
Create a Global class, which extends GlobalSettings, and bind interface to implementation in configure():
public class Global extends GlobalSettings {
private Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(TestInferface.class).to(TestImpl.class);
}
});
}
In your Controller or any other class, use the #Inject annotation to get an instance of the interface:
#Inject
private Test test;
2) Dependency Injection for Play Controller
Override GlobalSettings.getControllerInstance to manage controller class instantiation either via Guice:
#Override
public <A> A getControllerInstance(Class<A> controllerClass) throws Exception {
return injector.getInstance(controllerClass);
}
How to use the Guice injection?
GET /test1 #controllers.ApplicationTest1.index()
GET /test2 #controllers.ApplicationTest2.index()
Route definitions starting with # will be managed by play.GlobalSettings#getControllerInstance method.
Is there a better way to consume a service in mvvmcross by constructor injection?
For example, I have my object in a plugin implementation
public class MyObject : IMyObject
{
public MyObject (int id)
{
_id = id;
}
}
and want to consume it somewhere the portable core (in the buisness layer) like this :
public void ConsumeTheService()
{
int i = 50;
var myObject = this.GetService<IMyObject>(i);
}
Actually, I only use a setter to get my id back in the implementation.
Following your update... if you are asking about how to get:
var myObject = this.GetService<IMyObject>(50);
and for this to return an object which is initiaised as new MyObject(50)
then I would instead recommend that you implement an interface
public interface IMyObjectFactory
{
IMyObject CreateMyObject(int i);
}
with an implementation:
public class MyObjectFactory : IMyObjectFactory
{
public IMyObject CreateMyObject(int i)
{
return new MyObject(i);
}
}
you can then register this IMyObjectFactory with IoC
I'm not sure I understand your example - not sure what intValue does in GetService
Regardless:
MvvmCross v3 includes constructor injection - see some details on http://slodge.blogspot.co.uk/2013/03/v3-new-viewmodel-lifecycle.html
Others have also implemented constructor injection within vNext - e.g. https://github.com/gshackles/CrossBar/ and http://slodge.blogspot.co.uk/2013/02/a-second-take-on-constructor-injection.html
The IoC within MvvmCross is completely replaceable - so you can use other IoC mechanisms if you want to (but this does require some code from you)
I have the following class:
public class MyClass {
#Inject
private MyAnotherClass myAnotherClass;
public MyClass() {
//Perform operations on myAnotherClass.
}
}
I need to do some things in constructor which require an instance of myAnotherClass. Unfortunately myAnotherClass is injected after code in constructor is ran, which means I am performing operations on null...
I could of course instantiate it the classic way (MyAnotherClass myAnotherClass = new MyAnotherClass()) directly in constructor, but I don't think it is the right thing to do in this situation.
What solutions would you suggest to solve this problem?
Best option:
public class MyClass {
private final MyAnotherClass myAnotherClass;
public MyClass(MyAnotherClass other) {
this.myAnotherClass = other;
// And so forth
}
}
T5-IoC will then use constructor injection so there's no need to 'new' up MyClass yourself. See Defining Tapestry IOC Services for more info.
Alternatively:
public class MyClass {
#Inject
private MyAnotherClass myAnotherClass;
#PostInjection
public void setupUsingOther() {
// Called last, after fields are injected
}
}
I'd like to create an Inter-Type declaration that declares a (static final) Logger instance inside each class.
The constructor should be passed the enclosing class Klazz.class value:
#Aspect
public class LoggerAspect {
public interface Logger {
}
public static class LoggerImpl implements Logger {
private static final Logger logger =
new Logger(thisJoinPoint.getTarget().getClass()/*.getName()*/);
}
#DeclareParents(value="com.my.api..*",defaultImpl=LoggerImpl.class)
private Logger implementedInterface;
}
I wrote the above solution, however I'm unable to use thisJoinPoint outside of an AspectJ advice.
If the Logger default implementation is applied to some class Klazz, how can I modify the above code to successfully pass Klazz.class to the Logger constructor?
You can declare a static member on any single class via inter-type declaration:
public aspect LoggingAspect {
static Logger MyClass.someField = Logger.getLogger(MyClass.class.getName());
}
But this is not very flexible because you need to do it for each single class. I just wanted to mention it.
In order to add something which is not technically but effectively a static member to a class, just use per-type association for your logging aspect:
public aspect LoggingAspect
pertypewithin(org.foo..*) // per-type association
{
Logger logger;
after() : staticinitialization(*) { // run 1x after class-loading
logger = Logger.getLogger(
getWithinTypeName() // type associated with aspect instance
);
}
pointcut logged() : // what to log, e.g. public methods
execution(public * *(..)); // (pointcut could also be abstract
// and refined in sub-aspects)
before() : logged() {
logger.log(...); // logging action
}
}
An example similar to this one - it is a common pattern - can be found in Ramnivas Laddad's excellent book AspectJ in action (2nd edition), chapter 6.2.4. It is also mentioned in the AspectJ documentation.
This answer gives the correct solution, posted below for convenience. Additionally it uses AspectJ annotations which is the preferred notation nowadays.
The developers recently added the annotation API, I presume with the intention of standardising the markup as many other popular libraries like Spring are also doing.
#Aspect("pertypewithin(com.something.*))")
public abstract class TraceAspect {
Logger logger;
#Pointcut
public abstract void traced();
#Pointcut("staticinitialization(*)")
public void staticInit() {
}
#After(value = "staticInit()")
public void initLogger(JoinPoint.StaticPart jps) {
logger = Logger.getLogger(jps.getSignature().getDeclaringTypeName());
}
#Before(value = "traced()")
public void traceThatOne(JoinPoint.StaticPart jps) {
logger.log(jps.getSignature().getName());
}
}