Get services extended from a certain interface - grails

Is possible to get all services extended from a certain interface in grails
So I can collect them within one service

Yes, I think you can do this by autowiring to List type. Let's say you have three implementations of an interface BaseService in grails-app/services as:
grails-app/services/exampleapp/BaseService.groovy
package exampleapp
interface BaseService {
}
grails-app/services/exampleapp/OneImplService.groovy
package exampleapp
class OneImplService implements BaseService {
}
grails-app/services/exampleapp/TwoImplService.groovy
package exampleapp
class TwoImplService implements BaseService {
}
Now, you can inject all implementations of BaseSerive as follows:
grails-app/services/exampleapp/TestService.groovy
package exampleapp
import org.springframework.beans.factory.annotation.Autowired
class TestService {
#Autowired
List<BaseService> baseServiceList
void doSomething() {
assert baseServiceList.size() == 2
}
}
Please note that the above example is tested with Grails 5 web application. But, I would be surprised if this does not work in the previous versions of Grails.

Related

Cannot import package in unit tests for a Jenkins Shared Library

I'm attempting to create unit tests for a JenkinsShared library using Gradle in order to run the test tasks.
I've followed this tutorial which upon conclusion one has a working test suite for a shared library for functions within the vars folder (with the unit tests in src/test/groovy/*Test.groovy).
However, in our internal shared jenkins library we followed a more object oriented style and isolated functionality into a package of classes in the format: src/org/company/*.groovy.
The problem arises when attempting to import said package into a unit test class. In the tutorial, the functions are imported using the loadScript method this method fails when loading a class which is dependent on another file.
Take the class:
package tests
import org.junit.*
import com.lesfurets.jenkins.unit.*
import static groovy.test.GroovyAssert.*
import org.company.UtilFactory
class UtilFactoryTest extends BasePipelineTest {
#Test
void testCall() {
def util = UtilFactory.getUtil("hello")
assertEquals true, true
}
}
src/org/company/UtilFactory.groovy
package org.company
class UtilFactory implements Serializable {
static Util instance
static Util getUtil(script=null) {
if (!(UtilFactory.instance)) {
if (!script) {
// Throws an exception if on the first call to getUtil the
// script parameter is null.
throw new ScriptUndefinedException("script parameter null on initial call to getUtil")
}
UtilFactory.instance = new Util(script)
}
return UtilFactory.instance
}
}
class ScriptUndefinedException extends Exception {
// Parameterless Constructor
public ScriptUndefinedException() {}
// Constructor that accepts a message
public ScriptUndefinedException(String message)
{
super(message);
}
}
Which gives me the exception:
jenkins-utilities/src/test/groovy/UtilFactoryTest.groovy: 7:
unable to resolve class org.company.UtilFactory
# line 7, column 1.
import org.company.UtilFactory
This may be more of a Gradle issue than a JenkinsShared Library. I've just spent a good portion of my day trying to figure out exactly what I'm doing wrong to no avail.
I would really appreciate any help to guide me in the right direction.
This library may be helpful getting your shared libraries to work in the unit test https://github.com/stchar/pipeline-sharedlib-testharness

Guice Binding from Consumer Package

I am newbie for Guice and seeking help for the following use case :
I have developed one package say (PCKG) where the entry class of that package depends on other class like:
A : Entry point class --> #Inject A(B b) {}
B in turn is dependent on C and D like --> #Inject B(C c, D d) {}
In my binding module I am doing :
bind(BInterface).to(Bimpl);
bind(CInterface).to(CImpl);
...
Note I am not providing binding information for A as i want to provide its binding by its consumer class. (this is how the design is so my request is to keep the discussion on main problem rather than design).
Now my consumer class is doing like:
AModule extends PrivateModule {
protected void configure() {
bind(AInterface.class).annotatedWith(AImpl.class);
}
}
Also in my consumer package:
.(new PCKGModule(), new AModule())
Q1. Am i doing the bindings correctly in consumer class. I am confused because when i am doing some internal testing as below in my consumer package:
class testModule {
bind(BInterface).to(Bimpl);
bind(CInterface).to(CImpl)...
}
class TestApp {
public static void main(..) {
Guice.createInstance(new testModule());
Injector inj = Guice.createInstance(new AModule());
A obj = inj.getInstance(A.class);
}
}
It is throwing Guice creation exception.Please help me get rid of this situation.
Also one of my friend who is also naive to Guice was suggesting that I need to create B's instance in AModule using Provides annotation. But i really didn't get his point.
Your main method should look like this:
class TestApp {
public static void main(..) {
Injector injector = Guice.createInjector(new TestModule(), new AModule());
A obj = injector.getInstance(A.class);
}
Note that the Java convention is for class names to have the first letter capitalised.
I'm pretty sure your implementation of AModule isn't doing what you think it's doing either, but it's hard to be certain based on the information you've provided. Most likely, you mean to do this:
bind(AInterface.class).to(AImpl.class)`
There's no need to do anything "special" with A's binding. Guice resolves all the recursion for you. That's part of its "magic".
annotatedWith() is used together with to() or toInstance(), like this:
bind(AInterface.class).to(AImpl.class).annotatedWIth(Foo.class);
bind(AInterface.class).to(ZImpl.class).annotatedWIth(Bar.class);
Then you can inject different implementations by annotating your injection points, e.g.:
#Inject
MyInjectionPoint(#Foo AInterface getsAImpl, #Bar AInterface getsZImpl) {
....
}
It's worth also pointing out that you can potentially save yourself some boilerplate by not bothering with the binding modules (depending how your code is arranged) and using JIT bindings:
#ImplementedBy(AImpl.class)
public interface AInterface {
....
}
These effectively act as "defaults" which are overridden by explicit bindings, if they exist.

Context & Dependency Injection : How to inject implementation of an interface?

I am at beginner stage of CDI and trying to inject the implementation of interface using field injection as below:
AutoService.java
package com.interfaces;
public interface AutoService {
void getService();
}
BMWAutoService.java
package com.implementations;
import javax.inject.Named;
import com.interfaces.AutoService;
#Named("bmwAutoService")
public class BMWAutoService implements AutoService {
public BMWAutoService() {
// TODO Auto-generated constructor stub
}
#Override
public void getService() {
System.out.println("You chose BMW auto service");
}
}
AutoServiceCaller.java
package com.interfaces;
public interface AutoServiceCaller {
void callAutoService();
}
AutoServiceCallerImp.java
package com.implementations;
import javax.inject.Inject;
import javax.inject.Named;
import com.interfaces.AutoService;
import com.interfaces.AutoServiceCaller;
public class AutoServiceCallerImp implements AutoServiceCaller {
#Inject
#Named("bmwAutoService")
private AutoService bmwAutoService;
public AutoServiceCallerImp() {
}
#Override
public void callAutoService() {
bmwAutoService.getService();
}
}
TestDisplayMessage.java
package com.tests;
import com.implementations.AutoServiceCallerImp;
import com.interfaces.AutoServiceCaller;
public class TestDisplayMessage {
public TestDisplayMessage() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
AutoServiceCaller caller = new AutoServiceCallerImp();
caller.callAutoService();
}
}
When I run TestDisplayMessage.java , the expected result would be "You chose BMW auto service" but I get NullPointerException as below :
Exception in thread "main" java.lang.NullPointerException
at com.implementations.AutoServiceCallerImp.callAutoService(AutoServiceCallerImp.java:21)
at com.tests.TestDisplayMessage.main(TestDisplayMessage.java:16)
Couldn't figure out exactly what I am missing here. Please help.Thanks in advance.
Ok, it seems you misunderstood the concept of CDI a bit - the idea is that you leave the bean lifecycle to CDI container. That means CDI will create a dispose beans for you. In other words, you are not supposed to create beans by calling new. If you do that, CDI does not know about it and will not inject anything into it.
If you are in SE environment, which I think you are since you use main method to test, you want to use Weld (CDI implementation) SE artifact (I guess you do that).
There, you will need to start the CDI container. Note that if you were developing a classical EE application on a server, you don't do this, because the server will handle it for you. Now, the very basic way to boot Weld SE container is:
Weld weld = new Weld();
try (WeldContainer container = weld.initialize()) {
// inside this try-with-resources block you have CDI container booted
//now, ask it to give you an instance of AutoServiceCallerImpl
AutoServiceCallerImpl as = container.select(AutoService.class).get();
as.callAutoService();
}
Now, second issue with your code. The usage of #Named is intended for EL resolution. E.g. in JFS pages, so you can access the bean directly. What you probably want is to differentiate between several AutoService implementations and choose a given one. For that CDI has qualifiers. Check this documentation section for more information on how to use them.

Dependency Injection in Angular 2

I thought DI was implemented to allow use the same services over the application, and change them as needed. However this snippet (Angular 2.0.0-beta.0) refuses to work:
# boot.ts
import {ProjectService} from './project.service'
bootstrap(AppComponent, [ProjectService]);
# my.component.ts
export class MyComponent {
constructor(project: ProjectService) {
}
}
and with explicit service requirement it works:
# my.component.ts
import {ProjectService} from './project.service';
export class MyComponent {
constructor(project: ProjectService) {
}
}
The official doc is somewhat inconsistent, but has the same in the plunkr example:
# boot.ts
import {HeroesListComponent} from './heroes-list.component';
import {HeroesService} from './heroes.service';
bootstrap(HeroesListComponent, [HeroesService])
# heroes-list.component.ts
import {HeroesService} from './heroes.service';
Is this the intended way of DI usage? Why we have to import service in every class requiring it, and where are the benefits if we can't just describe the service once on boot?
This isn't really related to dependency injection. You can't use a class in TS that is not imported.
This line references a class and DI derives from the type what instance to inject.
constructor(project: ProjectService) {
If the type isn't specified by a concrete import, DI can't know which of all possible ProjectService classes should be used.
What you can do for example, is to request a type (ProjectService) and get a different implementation (subclass like MockProjectService or EnhancedProjectService,...)
bootstrap(HeroesListComponent, [provide(ProjectService useClass: MockProjectService)]);
this way DI would inject a MockProjectService for the following constructor
constructor(project: ProjectService) {

dependency injection with OSGI

I have built an application with the dependency framework Guice. Now I will move over to OSGI and started to extend my jars with bundle information.
The main problem, which I currently face is, how to set up the dependency injection correctly. I have bundle A, which exports some packages. Then Bundle B defines a component, which needs some object (class AA) of bundle A injected.
I could set up a service for the class AA in bundle A, which will be injected automatically, but what if bundle A has also a dependency to some class in bundle A, which is maybe not exported. Do I have to set up the second class then also as service, which will not work, because it is not exported.
The following code will show the problem:
Bundle A
package test.bundleA.api
public class AA {
#Inject
public AA(AInternal someReference) {...}
}
package test.bundleA.internal
public class AInternal {...}
Bundle B:
package test.bundleB.api
public class ComponentB {
#Inject
public ComponentB(AA refToA) {...}
}
When I will use any other classes in bundle A from the exported package, do I have then to set up for each of them a service?
What is a common approach to solve the problem of dependency injection inside the bundle and even over bundle boundaries?
If you are independent of using Guice I would recommend to use Eclipse+Bndtools to create your OSGi bundles. With Bndtools, its quite easy to create OSGi bundles and also DI via Annotations. Let's take an example:
You have an interface in bundleA:
public interface Greeting {
String sayHello(String name);
}
An implementation in bundleB where #Component enables our bundle to use OSGi Declarative Service.
#Component
public class ExampleComponent implements Greeting {
public String sayHello(String name) {
return "Hello " + name;
}
}
And in the end a third bundleC where you want to us DI and inject all Greeting implementation to a specific component for usage.
#Component
public class GreetingCommand {
private Greeting greetingSvc;
#Reference
public void setGreeting(Greeting greetingSvc) {
this.greetingSvc = greetingSvc;
}
public void greet(String name) {
System.out.println(greetingSvc.sayHello(name));
}
}
As you can see with #Reference you indicate that you want to inject an implementation of your Greeting interface. The example above uses OSGi Declarative Services in combination with Bndtools. Bndtools itself takes the annotations and creates a XML file needed for OSGi to use Declarative Services. I don't want to go more deep into it. Please see [1] and [2] for more information. Just wanted to show you how DI is made by using declarative services and Bndtools.
[1] http://bndtools.org/
[2] http://wiki.osgi.org/wiki/Declarative_Services
Well, there is a extension library called Peaberry which provide integration Guice with OSGi. There is nice example how to inject a service bundle into another bundle.
Hope you will find it helpful.
The solution to your specific scenario is to define a public factory (builder) service/component that you can register with osgi and inject that type. The factory impl can be defined in the same module, and create the internal type via a 'create' or 'build' method with a return type of a public interface type, but the impl is internal.

Resources