OSGi annotations (Activate, Reference, Component) in Scala - scala

I am trying to write an OSGi service in Scala (most other services/bundles are written in Java) and I struggle a bit with the syntax.
Normally in Java one can use the #Activate annotation on a constructor like this:
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
#Component(configurationPid = "PID", service=AgentService.class, immediate=true)
public class AgentServiceImpl implements AgentService {
#Activate
public AgentServiceImpl(#Reference Service1 service1, #Reference Service2 service2) {
// ...
}
In Scala it should look somewhat like this:
import org.osgi.service.component.annotations.{Activate, Component, Deactivate, Reference}
#Component(
configurationPid = "PID",
service = Array(classOf[AgentService]),
immediate = true)
class AgentServiceImpl #Activate() (#Reference service1: Service1,
#Reference service2: Service2) implements AgentService {
// ...
}
When I try compiling this Scala code (with gradle) I geht the following error message:
error : In component xxx.xxxx.xx.xx.agent.AgentServiceImpl , multiple references with the same name: service1. Previous def: xxx.xxxx.xx.xx.service.Service1, this def:
error : In component xxx.xxxx.xx.xx.agent.AgentServiceImpl , multiple references with the same name: service2. Previous def: xxx.xxxx.xx.xx.service.Service2, this def:
Is this happening because my syntax concerning the annotations is wrong?
I am particularly not too sure about this #Activate() bit. In Java I don't need to use brackets here - but it does not compile without in Scala.
Does anyone know a sample project trying to do something similar?

I found the solution:
Compilation succeeds after adding val before the constructor paramters:
import org.osgi.service.component.annotations.{Activate, Component, Deactivate, Reference}
#Component(
configurationPid = "PID",
service = Array(classOf[AgentService]),
immediate = true)
class AgentServiceImpl #Activate() (#Reference val service1: Service1,
#Reference val service2: Service2) implements AgentService {
// ...
}
Probably this is because OSGi cannot properly deal with the automatically generated setter methods of service1 and service2.

Related

unit test failing if Log Member object (#Slf4j isn't found groovy.lang.MissingPropertyException: No such property: log for class:

I'm helping my development team with some logging code in our framework.
using spring AOP I've created a groovy class called LoggingAspect. Its main purpose is to log method execution times for classes in com.zions.comon.services.logging directories and
annotated with #Loggable.
Since some classes already have #sl4j logging I need to detect if hat log member objects exists and use the built in #slf4j logging for that class. If it doesn't I need to execute the #sl4j annotation in aspect logging code.
The first statement in the try block will check if log member exists on object. If it does, then iLog will get set to incoming object's logger. However I'm not sure how to complete the rest of the code Once I detect the log member object. I don't expect anyone to write this code for me but would appreciate any suggestions/areas of researcoh on how to do this - such as using "if"
The logic should go something like:
Intercept and calculate method logging times in select classes
Check for existing log member object that indicates #slf4j is already present in class
If log member object exits use #sl4j logging features already built into that class
If log member object doesnt exist use #slf4j logging in logging Aspect code.
any help would be appreciated
"logging flow diagram"
Reverted code to original version - My LoggingAspect code looks like this at the moment
package com.zions.common.services.logging
import groovy.util.logging.Slf4j
import org.slf4j.Logger
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.EnableAspectJAutoProxy
#Aspect
#Configuration
#Slf4j
#EnableAspectJAutoProxy(proxyTargetClass=true)
public class LoggingAspect {
*
* This is a Logging Aspect for the Loggable annotation that calculates method runtimes
* for all methods under classes annotated with #Loggable*/
/**
* Logs execution time of method under aspect.
*
* #param joinPoint - method under join
* #return actual return of method under join point.
* #throws Throwable
*/
#Around('execution (* *(..)) && !execution(* *.getMetaClass()) && #within(com.zions.common.services.logging.Loggable)')
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
def obj = joinPoint.this
Logger iLog = log
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - start;
try {
/*First statement of try block attempts to test if log members exist on object.
If it does, then iLog will get set to incoming object's logger*/
obj.log.isInfoEnabled()
iLog = obj.log
} catch (e) {}
iLog.info("${joinPoint.getSignature()} executed in ${executionTime}ms");
return proceed;
}
}
If its helpful my logging Annotation is
package com.zions.common.services.logging
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/* Logging annotation to be used at class level
* Loggable annotation for all methods of a class annotated with the #Loggable annotation*/
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface Loggable {}
I've added a junit test class that validates when log member is found - The line 'iLog = obj.log' get's called from the LoggingAspect code and the test is PASSING.
LoggingAspectSpecification.groovy
package com.zions.common.services.logging
import static org.junit.Assert.*
import groovy.util.logging.Slf4j
import org.junit.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Profile
import org.springframework.context.annotation.PropertySource
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
#ContextConfiguration(classes=[LoggingAspectSpecificationConfig])
class LoggingAspectSpecification extends Specification {
#Autowired
SomeClass someClass
def 'Main flow for timing log'() {
setup: 'class to be logged'
when: 'execute something with class testing log'
someClass.methodOne()
someClass.methodTwo()
then: 'validate something logged'
true
}
}
#TestConfiguration
#Profile("test")
#ComponentScan(["com.zions.common.services.logging"])
#PropertySource("classpath:test.properties")
class LoggingAspectSpecificationConfig {
#Bean
SomeClass someClass() {
return new SomeClass()
}
}
#Loggable
#Slf4j
class SomeClass {
def methodOne() {
log.info('run methodOne')
}
def methodTwo() {
log.info('run methodTwo')
}
}
However my unit test is failing with classes that do not have #Slf4j meaning it will execute with the logger of the aspect instead of the pointcut object. The full error trace is:
groovy.lang.MissingPropertyException: No such property: log for class: com.zions.common.services.logging.SomeClass2
at com.zions.common.services.logging.SomeClass2.methodOne(LoggingAspectSpecification2.groovy:55)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
at com.zions.common.services.logging.LoggingAspect.logExecutionTime(LoggingAspect.groovy:42)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:643)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:632)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:174)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.zions.common.services.logging.LoggingAspectSpecification2.Main flow for timing log(LoggingAspectSpecification2.groovy:27)
The second unit test code is below - (the only difference is that #Slf4j) is not present in the classes.
LoggingAspectSpecification2.groovy
package com.zions.common.services.logging
import static org.junit.Assert.*
import groovy.util.logging.Log
import groovy.util.logging.Slf4j
import org.junit.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Profile
import org.springframework.context.annotation.PropertySource
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
#ContextConfiguration(classes=[LoggingAspectSpecificationConfig2])
class LoggingAspectSpecification2 extends Specification {
#Autowired
SomeClass2 someClass2
def 'Main flow for timing log'() {
setup: 'class to be logged'
when: 'execute something with class testing log'
someClass2.methodOne()
someClass2.methodTwo()
then: 'validate something logged'
true
}
}
<!-- language: lang-groovy -->
#TestConfiguration
#Profile("test")
#ComponentScan(["com.zions.common.services.logging"])
#PropertySource("classpath:test.properties")
class LoggingAspectSpecificationConfig2 {
#Bean
SomeClass2 someClass2() {
return new SomeClass2()
}
}
<!-- language: lang-groovy -->
#Loggable
class SomeClass2 {
def methodOne() {
int x=10, y=20;
System.out.println(x+y+" testing the aspect logging code");
}
def methodTwo() {
int x=10, y=20;
System.out.println(x+y+" testing the aspect logging code");
}
}
I'm guessing something's wrong in my LoggingAspect code in the Try Catch block?
To resolve the error and get my unit test to pass without #Slf4j or #Log - I had to add a println statement to the SomeClass2 code as in,
int x=10, y=20;
System.out.println(x+y+" testing the apsect logging code");
adding #Log just gave it another built in log member similar to #Slf4j - adding the println statement and removing the #Log annotation force the LoggingAspect code to execute. Unit test is passing.

Inject service into class (not component) Angular2

I am struggling to find a way to inject a service into an class object in angular2.
* NOTE: This is not a component, just a class. *
export class Product {
id: number;
name: string;
manufacturer: string;
constructor(product: any) {
this.id = product.id;
this.name = product.name;
this.manufacturer = product.manufacturer;
}
The only solution I have come up with is to pass the service reference to the constructor whenever I create a new product... ie: instead of new Product(product) I would do new Product(product, productService) . This seems tedious and error prone. I would rather import the reference from the class and not messy up the constructor.
I have tried the ReflectiveInjector:
let injector = ReflectiveInjector.resolveAndCreate([ProductService]);
this.productService = injector.get(ProductService);
However, this creates an error No provider for Http! (ProductService -> Http) at NoProviderError.BaseError [as constructor] (Also I'm pretty sure this creates a new productService when I simple want to reference my singleton that is instantiated at the app level).
If anyone knows of a working solution I would be glad to hear it. For now i will pass the reference through the constructor.
Thanks
I was struggling with a similar issue, and what I ended up doing, was making the service a singleton as well as an Angular injectable.
This way you can inject via DI into Angular classes and call the static getInstance() method to get the singleton instance of the class.
Something like this:
import {Injectable} from "#angular/core";
#Injectable()
export class MyService {
static instance: MyService;
static getInstance() {
if (MyService.instance) {
return MyService.instance;
}
MyService.instance = new MyService();
return MyService.instance;
}
constructor() {
if (!MyService.instance) {
MyService.instance = this;
}
return MyService.instance;
}
}
There is no way to inject a service into a plain class. Angular DI only injects into components, directives, services, and pipes - only classes where DI creates the instance, because this is when injection happens.
To get Http from a custom injector, you need to add to it's providers like shown in Inject Http manually in angular 2
or you pass a parent injector that provides them
// constructor of a class instantiated by Angulars DI
constructor(parentInjector:Injector){
let injector = ReflectiveInjector.resolveAndCreate([ProductService]);
this.productService = injector.get(ProductService, parentInjector);
}
See also https://angular.io/docs/ts/latest/api/core/index/ReflectiveInjector-class.html

Neo4j 3.0.3 Stored procedures in Scala

Is there any sample Scala code available for creating stored procedures in Neo4j-3.0.3 ?
I have been trying to create one simple Scala based stored procedure. Below is the Error message I get when I copy my scala-jar file to the neo4j-plugins directory and start the neo4j server :
=================
Caused by: org.neo4j.kernel.lifecycle.LifecycleException: Component 'org.neo4j.kernel.impl.proc.Procedures#1ac0223' was successfully initialized, but failed to start. Please see attached cause exception.
at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:444)
at org.neo4j.kernel.lifecycle.LifeSupport.start(LifeSupport.java:107)
at org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.newFacade(GraphDatabaseFacadeFactory.java:140)
... 10 more
Caused by: org.neo4j.kernel.api.exceptions.ProcedureException: Unable to find a usable public no-argument constructor in the class `neoscala`. Please add a valid, public constructor, recompile the class and try again.
=================
The scala class that I have used is :
package neoproc
import org.neo4j.graphdb.GraphDatabaseService
import org.neo4j.procedure.Procedure;
import javax.ws.rs.core.{Context, Response}
class neoscala(#Context db: GraphDatabaseService) {
#Procedure
def alice():String = {
String.valueOf(db.execute( "MATCH (n:User) return n" ));
}
}
Your Scala class declares a constructor with a GraphDatabaseService argument, and the exception tells you that it only wants a no-argument constructor.
It's documented in both
the user documentation:
Only static fields and #Context-annotated fields are allowed in Procedure classes.
the Javadoc:
The procedure method itself can contain arbitrary Java code - but in order to work with the underlying graph, it must have access to the graph API. This is done by declaring fields in the procedure class, and annotating them with the Context annotation. Fields declared this way are automatically injected with the requested resource. This is how procedures gain access to APIs to do work with.
All fields in the class containing the procedure declaration must either be static; or it must be public, non-final and annotated with Context.
Apparently it's not possible to create a class with a public field in Scala, so you'll have to create a parent Java class with the public field, and extend it with your Scala class:
// ProcedureAdapter.java
public abstract class ScalaProcedureAdapter {
#Context
public GraphDatabaseService db;
}
// neoscala.scala
class neoscala extends ScalaProcedureAdapter {
// ...
}
Here is the solution for this :
We will create Class in scala :
class FullTextIndex extends JavaHelper {
#Procedure("example.search")
#PerformsWrites
def search(#Name("label") label: String,
#Name("query") query: String): Stream[SearchHit] = {
//declare your method
}
val nodes: Stream[Node] = db.index.forNodes(index).query(query).stream
val newFunction: java.util.function.Function[Node, SearchHit] = (node: Node) => new SearchHit(node)
nodes.map {
newFunction
}
}
private def indexName(label: String): String = {
"label-" + label
}
}
Procedure in Neo4j always return result in Stream and it is a latest feature in Java8 so we will also used Java Class for return the final result and For defining the public variable.
We will create Java class for result :
public class JavaHelper {
#Context
public GraphDatabaseService db;
#Context
public Log log;
public static class SearchHit {
//your result code here
}
You can refer knoldus blog for Neo4j User Defined Procedure for creating and storing Neo4j Procedure with Scala. Here you will also find sample code with git hub repository.

How to call Grails from Scala

Is there a way to call a method in a Grails service, from a Scala class that is running on the same JVM?
I have seen something similar done from Groovy/Griffon but cannot figure out how to accomplish that in Grails. (http://www.jroller.com/aalmiray/entry/griffon_groovy_scala_working_together)
Basically, one of my Grails controllers calls some Scala code, which should return some values asynchronously. So, I guess, the only way to return those values is by calling back a method in a Grails service.
I found a way of doing it, inspired by the link in the question above, and one of the FAQs in the Grails website.
On the Scala side:
Declare an object similar to the following:
package scalaCallback
object ScalaCallback{
var cback: {def callback(example: String)} = null
def setCallback(cb: {def callback(example: String)}){
cback = cb
}
def invokeCallback(example: String){
if(callback != null) cback.callback(example)
}
}
On the Grails side:
Create a class in src/groovy similar to the following:
package groovyCallback
import org.codehaus.groovy.grails.commons.ApplicationHolder
class GroovyCallback{
private GroovyCallback() {}
private static final INSTANCE = new GroovyCallback()
static getInstance(){ return INSTANCE }
void callback(String example){
ApplicationHolder.application.mainContext.yourService.yourMethod(example)
}
}
In your BootStrap.groovy init add the following:
scalaCallback.cback = groovyCallback.GroovyCallback.getInstance()
When you call invokeCallback("example") in Scala, it will call yourService.yourMethod("example")
Note: the jar file with your Scala class should be in the lib folder of you Grails application
Your Grails service is a Spring bean. #Autowire the service into your Scala class (it will need to be a bean/#Component) and call the method.
EDIT - added example:
For example (using Java, not Scala but the approach is exactly the same):
Java code calling service:
package grailstest;
#Component
public class ServiceInjectionTester {
#Autowired TestService testService;
public String testTheService() {
return testService.serviceMethod();
}
}
Service:
class TestService {
String serviceMethod() {
return "success"
}
}
In Config.groovy:
grails.spring.bean.packages = [ "grailstest" ]
You can also wire your Java/Scala bean into your Grails classes:
class TestController {
#Autowired
ServiceInjectionTester serviceInjectionTester
def index = {
render(text: serviceInjectionTester.testTheService())
}
}
References:
Grails Reference 8.4 - Using Services from Java
Spring: The Foundation for Grails

How to test annotation object in the class that implement AbstractModule

I got a question regarding binding and annotation.
I have the following class:
public class MailFacadeImpl implements MailFacade {
private final PersonDao personDao;
#Inject
public MailFacadeImpl(#Mail PersonDao personDao) {
super();
this.personDao = personDao;
}
The PersonDao is annotated with a custom annotation.
I would like to be able to test this annotation inside the class that implement AbstractModule.
here is a piece of code:
bind(new TypeLiteral<SecurityRulesFactory<Person>>(){}).toProvider(FactoryProvider.newFactory(
new TypeLiteral<SecurityRulesFactory<Person>>(){}, new TypeLiteral<MailSecurityRulesCrdb>(){}));
I would like to have somthing similar to :
if(PersonDAO is annotated with(Mail.class) ){
bind(new TypeLiteral<SecurityRulesFactory<Person>>(){}).toProvider(FactoryProvider.newFactory(
new TypeLiteral<SecurityRulesFactory<Person>>(){}, new TypeLiteral<MailSecurityRulesCrdb>(){}));
}
Do you think it's possible?
thx for your help :-)
Have a nice friday!
It's not clear why you want your module to do this test. Instead, your module can specify how to get or create an instance of PersonDao for injection points annotated with Mail:
bind(PersonDao.class).annotatedWith(Mail.class).to(EmailAwarePersonDao.class);
Note that your PersonDao.class.isAnnotationPresent(Mail.class) won't help here, since the PersonDao class itself isn't annotated with Mail; the parameter to the MailFacadeImpl constructor has that annotation. There are ways to test for that, but if you are trying to do that from a Guice module, you're probably doing something wrong.