Is it possible to annotate class constructor in Kotlin - annotations

Clarification
This questions was asked before kotlin hit version 1.0. Language syntax in example is obsolete now, please follow official docs.
I'm playing with kotlin and spring DI.
I want to use constructor-based dependency injection, so I need to annotate the constructor.
I tried following approach:
Configuration
Import(javaClass<DataSourceConfig>())
public open class AppConfig(dataSource: DataSource) {
private val dataSource: DataSource
Autowired {
this.dataSource = dataSource
}
}
Configuration
public open class DataSourceConfig {
Bean
public open fun dataSource(): DataSource {
// source omitted
}
}
But it doesn't work. Is it even possible to annotate constructor in kotlin?
P.S. I'm using Kotlin M10.1 and Spring 4.1.4
UPDATE:
Annotating constructor is possible in kotlin. The problem was that it's not allowed to use constructor-based DI for #Configuration

Hrm, I think the syntax has changed radically since this question was posted. The current way (according to the docs) is to add the keyword constructor between your class name and arguments and annotate that, i.e.
public class AppConfig #Configuration constructor(dataSource: DataSource) {
//...
}

Try to write:
Configuration
public open class AppConfig [Import(javaClass<DataSourceConfig>())] (dataSource: DataSource) {
//...
}

This syntax works for me:
Configuration
Import(javaClass<DataSourceConfig>())
public open class AppConfig {
private val dataSource: DataSource
Autowired constructor(dataSource: DataSource){
this.dataSource = dataSource
}
}

Related

Is there any way to force spring not to use/create '_class' field in the mapping?

The thing is on production servers we got mapping for Elasticsearch with dynamic set to strict. Currently, we use a rest level client to communicate with Elastisearch, however, we would like to migrate to spring-data-elasticsearch.
Unfortunately, it seems spring data force to use either _class or #TypeAlias which also interfere with the mapping itself. Is any way to use spring-data without _class or #TypeAlias?
Ok I have found a workaround for it.
Be aware of using it when your elasticsearch model uses inheritance.
To solve this problem create class like this:
public class CustomMappingEsConverter extends MappingElasticsearchConverter {
public CustomMappingEsConverter(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext, GenericConversionService conversionService) {
super(mappingContext, conversionService);
}
#Override
public Document mapObject(#Nullable Object source) {
Document target = Document.create();
if (source != null) {
this.write(source, target);
}
target.remove("_class"); // << workaround to remove those _class field in elasticsearch
return target;
}
}
And register the bean:
#Configuration
public class MappingEsConfiguration {
#Bean
#Primary
public CustomMappingEsConverter CustomMappingElasticsearchConverter(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext,
GenericConversionService genericConversionService) {
return new CustomMappingEsConverter(mappingContext, genericConversionService);
}
}
After this changes I was able to use spring data without additional field _class.
Currently this is not possible. There is an open issue for that.
Edit 25.04.2021:
this feature will be available from the next version (4.3) on.

Spring AOP : Interface method with Parameter annotation captured, but annotation is not present

I'm using Spring AOP to intercept a method execution.
I have an interface that looks like the following:
public interface MyAwesomeService {
public Response doThings(int id, #AwesomeAnnotation SomeClass instance);
}
Here is the implementation of the interface:
public class MyAwesomeServiceImpl implements MyAwesomeService {
public Response doThings(int id, SomeClass instance) {
// do something.
}
}
Now i would like any method which has a parameter annotated with #AwesomeAnnotation should be captured by Spring AOP.
So I wrote the following aspect which works.
#Aspect
#Component
public class MyAwesomeAspect {
#Around("myPointcut()")
public Object doAwesomeStuff(final ProceedingJoinPoint proceedingJoinPoint) {
final MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
// annotationMatrix is empty.
}
#Pointcut("execution(public * *(.., #package.AwesomeAnnotation (package.SomeClass), ..))")
public void myPointcut() {}
}
However when I try to find the parameter annotations I don't get any annotations back. As mentioned above, the annotationMatrix is empty.
So here are my questions:
Why is the annotationMatrix empty? Probably because parameter annotations are not inherited from an interface.
Why I'm able to capture the method execution. Since Spring AOP is able match the pointcut, Spring somehow is able to see the method's parameter annotations but when I try to see that using methodSignature.getMethod().getParameterAnnotations() it doesn't work.
I also faced this issue with one of my parameter annotations. I was able to fix the same by making sure that the parameter annotation definition had RetentionPolicy as RUNTIME and Target as PARAMETER
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
public #interface Param {
public String name();
}
The answers to your questions:
Parameter annotations are not inherited from interfaces to implementing methods. In fact, annotations are almost never inherited, only from class (not interface!) to subclass if the annotation type itself is annotated by #Inherited, see JDK API documentation.
Update: Because I have answered this question several times before, I have just documented the problem and also a workaround in Emulate annotation inheritance for interfaces and methods with AspectJ.
Because during compile or weave time AspectJ can match your pointcut against the interface method and thus sees the annotation.
You can fix the situation by adding the annotation to the parameter in your interface implementation, e.g. like this:
#Override
public Response doThings(int id, #AwesomeAnnotation SomeClass instance) {
// ...
}
Then with an aspect like this...
#Aspect
#Component
public class MyAwesomeAspect {
#Pointcut("execution(public * *..MyAwesomeService.*(*, #*..AwesomeAnnotation (*), ..)) && args(*, instance, ..)")
static void myPointcut(SomeClass instance) {}
#Around("myPointcut(instance)")
public Object doAwesomeStuff(Object instance, ProceedingJoinPoint proceedingJoinPoint) {
System.out.println(proceedingJoinPoint);
System.out.println(" instance = " + instance);
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
for (Annotation[] annotations : annotationMatrix) {
for (Annotation annotation : annotations) {
System.out.println(" annotation = " + annotation);
}
}
return proceedingJoinPoint.proceed();
}
}
... you get a console log similar to this:
execution(Response de.scrum_master.app.MyAwesomeServiceImpl.doThings(int, SomeClass))
instance = de.scrum_master.app.SomeClass#23fc625e
annotation = #de.scrum_master.app.AwesomeAnnotation()

JAX-RS #PathParam to inject in class member variable?

I want to do something like this:
#Stateless
#Path("/sensors/{sensorid}/version")
#Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
#Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public class SensorVersionRestView extends VersionRestView{
#PathParam("sensorid")
private String sensorid;
#GET
#Path("count")
// so the complete path is i.e.
// domain.com/rs/sensors/111211/version/count
public void getCount() {
// do something with the sensorId....
}
}
But the only thing I get is null on runtime (I use Glassfish v3 with Jersey). The compiler and eclipse never mentions a problem with the #PathParam at the member class variable.
What's wrong with my construct?
The main problem is, why I doesn't want to use the whole path on each method in this class, that there exists another class which handles some rest operations on the sensor layer (deomain.com/rs/sensors/count i.e.)
I believe you need to change it to this:
#Stateless
#Path("/sensors/{sensorid}/version")
public class SensorVersionRestView extends VersionRestView {
#GET
#Path("count")
#Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
#Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
// domain.com/rs/sensors/111211/version/count
public void getCount(#PathParam("sensorid") String sensorid) {
// do something with the sensorId....
}
}
Because injection occurs at object
creation time, use of this annotation
on resource class fields and bean
properties is only supported for the
default per-request resource class
lifecycle. Resource classes using
other lifecycles should only use this
annotation on resource method
parameters. - JSR-311 Javadocs
You should be able to annotate fields with #PathParam as long as the resource class lifecyle is per-request. By default the life-cycle of root resource classes is per-request.
EDIT: I don't think you can achieve this using EJBs. If you remove the #Stateless annotation, it should work.

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.