Cannot use java value as parameter to java annotation on scala function - scala

I have 3 java files: HW.java, myAnn.java, and Constants.java in package myApp.
Constants.java:
public final class Constants {
public static final String WORLD ="World";
}
myAnn.java:
public #interface myAnn {
java.lang.String name() default "";
}
HW.java:
class HW {
#myAnn(name = Constants.WORLD)
public static void main(String[] args){
System.out.println("Hi "+ Constants.WORLD);
}
}
My app compiles and runs fine as shown above, but I want to migrate HW.java to scala as
HelloWorld.scala:
object HelloWorld {
#myAnn(name = Constants.WORLD)
def main(args: Array[String]) {
println("Hello " + Constants.WORLD)
}
}
When I try to compile this, I get
error: annotation argument needs to be a constant; found:
Constants.WORLD #myAnn(name = Constants.WORLD)
If I remove the annotation then HelloWorld compiles and executes as expected.
Why can I use Constants.WORLD as a parameter to an annotation from a java program, but not from a scala program? Is there something I can modify in Constants.java to allow it to be used from either java or scala? I can't modify MyAnn.java, and I can't migrate Constants.java yet.

It is a bug that only shows up when feeding the java source files into the scala compiler, see issue SI-2764. The example works when compiling the java files first using javac and then pointing scalac's classpath to the generated classfiles.

Related

Annotations on file classes

In my current code (Java), I'm doing some custom annotation processing using class-level Java annotations i.e. the annotations are #java.lang.annotation.Target({ElementType.TYPE}).
The target classes contain only static utility methods, so I used file-scoped functions in Kotlin. How do I add these annotations to the generated Kt class?
In Java:
// Utils.java
package com.example;
#MyCustomAspect
public void Utils {
public static void doStuff() {
System.out.println("Hello";
}
}
Now in Kotlin:
// Utils.kt
package com.example;
// ??? #MyCustomAspect ???
fun doStuff() {
System.out.println("Hello";
}
You can use AnnotationTarget.FILE to allow for Kotlin defined annotation to target the Kt class generated from a .kt file. Java defined annotation with target ElementType.TYPE can also be used to target Kotlin file class:
#file:MyCustomAspect
package org.example
#Target(AnnotationTarget.FILE)
annotation class MyCustomAspect
fun doStuff(){
}

Powermockito mock operation on hierarchy level class

My app has hierarchy level class objects as follows.
Package com.sample.folder1;
Public class ParentClass{ }
Package com.sample.folder2;
Public class Childclass1 extends ParentClass{ }
Unit piece under test package:
#Test
Public void testMocking{
Childclass1 obj = Powermockito.mock(Chilclass1.class);
}
When I execute above junit in eclipse it throws
"VerifyError: Inconsistent stackmap frames....."
Please suggest mocking on hierarchy classes on same and different packages.
Try to add -noverify (Java 8) or -XX:-UseSplitVerifier (Java 7) as vm parameter.

GWT Arrays.asList not working on interface types

Working on a GWT project (2.7.0), i have experienced a very odd client code behaviour.
The following code throws the error "SEVERE: (ReferenceError) : Ljava_io_Serializable_2_classLit_0_g$ is not definedcom.google.gwt.core.client.JavaScriptException: (ReferenceError) : Ljava_io_Serializable_2_classLit_0_g$ is not defined".
The error occurs, when calling Arrays.asList() with a parameter, that has an interface type.
Is this expected behaviour or a GWT bug?
// Working
Integer n1 = 1;
Arrays.asList(n1);
// Not working
Serializable n2 = 1;
Arrays.asList(n2);
GWT 2.7's Super Dev Mode (and from the _g$ in your class literal field, I think that is what you are using) has been observed having other issues like this, but when compiled the issues go away.
If this is indeed what you are seeing, the issue seems to be fixed in 2.8, not yet released: https://groups.google.com/d/topic/google-web-toolkit/RzsjqX2gGd4/discussion
This behavior is definitely not expected, but if you can confirm that this works correctly when compiled for production and in GWT 2.8, then we at least know the bug is fixed.
Well, the typical use of Arrays.asList would be
Object myObj = new Object();
List theList = Arrays.asList(new Object[] {myObj});
This works in GWT with any kind of interface/class/enum you throw at it.
EDIT : I've tested this with GWT 2.5.1 :
public class Foo implements EntryPoint {
public static interface MyInterface {
}
public static class MyObject implements MyInterface {
}
public void onModuleLoad() {
MyInterface myObject = new MyObject();
List<MyInterface> myList = Arrays.asList(myObject);
}
}
Isn't it possible that the problem lies somewhere else?

Inter Type Declaration on Compiled Class File

Is it possible to do Inter Type Declarations with AspectJ on Compiled Class Files at Load Time Weaving?
As an example: I compile some Groovy code and want to add fields or methods with IDT.
Update:
Oh my goodness, you do not need reflection to access members or execute methods. Eclipse shows errors in the editor, but you may just ignore them, the code compiles and runs fine anyway. So the aspect is really much more strightforward and simple:
public aspect LTWAspect {
public static String Application.staticField = "value of static field";
public String Application.normalField = "value of normal field";
public void Application.myMethod() {
System.out.println(normalField);
}
void around() : execution(void Application.main(..)) {
System.out.println("around before");
proceed();
System.out.println("around after");
System.out.println(Application.staticField);
new Application().myMethod();
}
}
Original answer:
Yes, but you have a hen-and-egg problem there, i.e. you cannot just reference the newly introduced fields from your LTW aspect code without reflection. (The last sentence is not true, see update above.) Plus, in order to make your LTW aspect compile, you need the classes to be woven on the project's build path so as to be able to reference them. Example:
Java project
public class Application {
public static void main(String[] args) {
System.out.println("main");
}
}
AspectJ project
import org.aspectj.lang.SoftException;
public aspect LTWAspect {
public static String Application.staticField = "value of static field";
public String Application.normalField = "value of normal field";
public void Application.myMethod() {
try {
System.out.println(Application.class.getDeclaredField("normalField").get(this));
} catch (Exception e) {
throw new SoftException(e);
}
}
void around() : execution(void Application.main(..)) {
System.out.println("around before");
proceed();
System.out.println("around after");
try {
System.out.println(Application.class.getDeclaredField("staticField").get(null));
Application.class.getDeclaredMethod("myMethod", null).invoke(new Application());
} catch (Exception e) {
throw new SoftException(e);
}
}
}
So, e.g. in Eclipse you need to put the Java project on the AspectJ project's build path under "Projects" because only then it can see Java class Application on which you want to declare members. After compilation you just start the Java project and do LTW on the aspect project (don't forget an aop-ajc.xml referencing LTWAspect).
In my example above I declare a static member, a non-static ("normal") member and a non-static method. My advice prints the static member and calls the non-static method, both via reflection. The non-static method then prints the non-static member, again via reflection. This is not nice, but it works and proves the ITD in combination with LTW is possible. There might be a more elegant way, but if so I am unaware of it. (Update: There is a more elegant way: Just ignore the errors marked by Eclipse IDE, see above.)
Program output
around before
main
around after
value of static field
value of normal field

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