MWE2 Workflow component with Scala language - java

I'm trying to write a MWE2 workflow component using scala language.
Below is the scala code:
package com.ford.modelling.workflow
import org.eclipse.emf.mwe2.runtime.workflow.{IWorkflowComponent, IWorkflowContext}
class SayHello extends IWorkflowComponent {
var message : String = null;
def preInvoke {}
def invoke(ctx : IWorkflowContext) { System.out.println(message) }
def postInvoke {}
}
and below is the workflow code:
module com.ford.modelling.workflow.SomeWorklow
SayHello {}
I can't figure out why does this workflow complain for error:
'com.ford.modelling.workflow.SayHello' does not have a public default constructor.

I'd assume that the scala IDE plugin does not mimic the java protocol completely, e.g. the IType does not expose a no-args constructor. You may want to ask the scale folks about it.
The error message should vanish as soon as you add a default constructor explicitly. Does that make sense?
A quick google search indicated that there probably no syntax for a default constructor so I'd assume it's a scala tooling problem. Does the problem occur at runtime, too?

Related

Kotlin Error : 'public' function exposes its 'public/*package*/' return type argument

I am new to Kotlin and trying out to write some project using the language.
I am using Java library and extending a class from the library in my project and I am seeing this error message.
'public' function exposes its 'public/*package*/' return type argument FooSettings
I understand the problem is but I am not sure how to fix it in Kotlin since I am still trying get familiar with Kotlin.
I can see that Kotlin is being smart and only trying to return of type that extends FooSettings. However the problem is FooSettings is package public only which means that I cannot access if in my Kotlin project.
I did some research about Kotlin generics and use of in or out but I wasn't able to fix the problem.
Is there any work around that I can do in my Kotlin project to fix the error I am seeing?
Code snippet
This is sample of Java library class:
Note, I have no way to changing the implementation of the library. I must use this Library and extend it in Kotlin.
It seems odd to me that the java library is written such a way and expect it to be overridden but that is question for another day.
import java.util.Collections;
import java.util.List;
public abstract class ClassA {
public List<FooBuilder<?>> getBuilder(Foo foo) {
return Collections.emptyList();
}
}
public class Foo {
}
public abstract class FooBuilder<U extends FooBuilder.FooSettings> {
// implementation of Class
abstract static class FooSettings {
// implementation of Class
}
}
Normally Java classes would override the method like such:
import java.util.List;
public class MyJavaClassA extends ClassA {
#Override public List<FooBuilder<?>> getBuilder(final Foo foo) {
// implementation
}
}
But I am trying to write in Kotlin such that it looks like: Reminder that this Kotlin is depending on the Java library and does not have access to package public classes.
class MyKotlinClassA : ClassA() {
override fun getBuilder(foo: Foo): MutableList<FooBuilder<*>> {
// implementation
}
}
This causes error
'public' function exposes its 'public/*package*/' return type argument FooSettings
I presume that by "package public" you meant "package private"? In your example, FooBuilder.FooSettings has no visibility modifier so uses the Java default of package private. Assuming that's what you meant...
You will be able to access the package private class, FooSettings, in your Kotlin code, but only if you put that Kotlin code in a package matching the one where FooSettings is declared.
You'll still get the same compilation error, but that's not because you can't access the type: it's because you're trying to use it in a context which is more visible than the type's declaration. i.e. you're trying to take a package private type and use it as part of a public method's signature, which isn't allowed. To get round that problem you need to mark your Kotlin class as internal.
It's might also be worth mentioning that internal for Kotlin means it's visible in that module, not in that package. This is all explained in more detail here.
In my case, I was getting this error because I was importing a kotlin class variable from another java file which raised because of the auto conversion from java to kotlin by Android Studio.
I was able to fix it by changing all the references of the variable in the java file to its setters and getters.
eg:
// kotlin file
internal open class BubbleBaseLayout : FrameLayout {
var windowManager: WindowManager? = null
lateinit var viewParams: WindowManager.LayoutParams
// defined here
var layoutCoordinator: BubblesLayoutCoordinator? = null
// ...
}
// Java file
// This variable
if (layoutCoordinator != null) { ... }
Needs to be changed to
// layoutCoordinator to getlayoutCoordinator everywhere
if(getlayoutCoordinator() != null){ ... }

Kotlin's JvmDefault - still need to declare the method ?

I am building my Spring Boot 1.5 + Kotlin 1.2.41 project into a jar. One of the interfaces in the jar has the #JvmDefault and it compiles fine with the flag (if I remove the flag, it fails).
Now, I am trying to use this interface in another java project, in which I define the Kotlin project as a dependency.
In one implementing class, I don't override the default method. Intellij seems to be OK with it, as it doesn't complain. However, when I compile with Maven, I get :
[ERROR] attempting to assign weaker access privileges; was public
If I implement the method (with some dummy implementation), then it compiles... but it defeats the purpose of the default interface.
Any idea what could be wrong ?
When opening the Kotlin interface code from the java project, here's the decompiled code I see :
public interface CrawlerOutput {
#kotlin.jvm.JvmDefault public open fun finalize(): kotlin.Unit { /* compiled code */ }
public abstract fun output(analyzedRepository: com.myCompany.Repository): kotlin.Unit
}
My java code implementing the interface :
public class CsvOutput implements CrawlerOutput {
#Override
public void output(Repository repository) throws IOException {
log.info("own output is receiving some data !");
}
/**
* IF I REMOVE BELOW METHOD, MAVEN CAN'T COMPILE IT ANYMORE,
* COMPLAINING OF WEAKER ACCESS PRIVILEGE
*/
#Override
public void finalize(){
}
}
Am I missing something ?
Thanks
Vincent
Your method name conflicts with java.lang.Object.finalize(). The error should be fixed if you choose a different method name.
Android Studio and JVM always update its versions. As a result of that some of you may experience this error message.
Inheritance from an interface with '#JvmDefault' members is only allowed with -Xjvm-default option
Don't worry . The solution is very simple. Just add below code part to the end of android block of your app level build.gradle file and sync.
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
freeCompilerArgs += [
"-Xjvm-default=all",
]
}
}

The scala plugin for IDEA 12.x not working as expected with akka

I am trying to use akka with maven and scala and I have added the akka actor jars to my pom.
Now in IDEA I go ahead and type this up,
class HelloWorld extends Actor {
}
At this point it correctly highlights HelloWorld as in error. I try to fix the errors and it correctly says that I have unimplemented methods (receive). I say go ahead and add the method and it does nothing.
I am using
IDEA 12.1.6
Scala plugin 0.22.302
Mac OSX 10.9.2
Note that if I created a trait myself
trait MyTrait {
def foo : Void
}
and tried to implement it like so
class MyImpl extends MyTrait {
}
Then I am correctly prompted for methods to be added and it does add the methods when I say go ahead.

instantiating a Scala class using reflection Java's `newInstance`

For some special use-case I have a small utility to load Java classes from jars using a dynamic class loader DynamicClassLoader. This works fine for Java classes contained in jars. Loading Scala classes from a jar also works without problems. However, instantiating the loaded Scala class leads to the following exception. It looks like the Scala class has private default constructor? Note the compiled Scala class name ending with $
java.lang.IllegalAccessException: Class XXX can not access a member of class ScalaClassYYY$ with modifiers "private"
The snippet below illustrates the idea of what I'm trying to achieve and gives a bit more context. The exception happens at the annotated line:
// deploy and register the new code
byte[] jarBytes = (byte[]) ((Object) message.getAttachment("jar"));
String registerClassName = message.getAttachment("register");
logger.debug("the register is '" + registerClassName + "'");
DynamicClassLoader loader = new DynamicClassLoader(jarBytes);
Class<?> registerClass = loader.lookUp(registerClassName);
// ===> this is where the java.lang.IllegalAccessException happens
IRegisterExecutor registerExecutor = (IRegisterExecutor) registerClass.newInstance();
registerExecutor.register();
Any ideas how to fix?
Obviously, you need to make the default constructor public (it won't work for Java classes without a public default constructor either). E.g.
class ScalaClassYYY() {
...
}
or if you want primary constructor to take some arguments,
class ScalaClassYYY(arg1: Int) {
def this() = this(0)
}
But from
Note the compiled Scala class name ending with $
it seems like you are actually trying to instantiate a Scala object:
object ScalaClassYYY { ... }
In this case, you shouldn't create a new instance and instead use the existing one:
(IRegisterExecutor) registerClass.getField("MODULE$").get(null);
EDIT:
I don't see in your answer how you add a default public constructor to a Scala class that does NOT require any parameters.
A class (not an object) that doesn't require any parameters has a default public constructor already (my first example).
Actually in Java all classes by default offer a public default constructor
No. Only those classes which have no constructors which take arguments.
remove the "(it won't work for Java classes without a public default constructor either)" because it is wrong
The documentation for Class.newInstance() says
IllegalAccessException - if the class or its nullary constructor is not accessible.
So I am pretty sure it's right. If it does work for Java classes without a public default constructor, this seems to be a major bug in the class loader you use. You can test it with a Java class which looks like this:
public class TestClass implements IRegisterExecutor {
public TestClass(int dummy) {}
// some implementation for IRegisterExecutor methods to get it to compile
}

type definition in a package object "hijacking" the inheritance of a java class in scala code

I have the following situation:
I have a Java class hierarchy like this:
package org.foo.some;
public class Model extends org.foo.some.GenericModel { // ... }
package org.bar;
public class MyModel extends org.foo.some.Model { // ... }
where org.foo.some.Model and org.foo.some.GenericModel are out of my reach (not my code). In Scala, also out of my reach, there is:
package org {
package foo {
package object some {
type Model = org.foo.some.ScalaModel
}
}
}
This leads to a funny behavior in Scala code, e.g.
val javaModel:MyModel = new org.bar.MyModel()
trait FooTrait[T <: org.foo.some.GenericModel] { // ... }
class FooClass extends FooTrait[MyModel] { //... }
does not compile and raises the following error:
type arguments [org.bar.MyModel] do not conform to trait FooTrait's type
parameter bounds [T <: org.foo.some.GenericModel]
Further, I can't invoke any method of org.foo.some.Model nor of org.foo.some.GenericModel on javaModel:
javaModel.doSomething()
raises
value create is not a member of org.bar.MyModel
I am under the impression that the package object is "hijacking" the visibility of the Java class hierarchy in Scala code. Indeed, ScalaModel does not extend org.foo.some.GenericModel.
Is there maybe a way to still access the hierarchy from within Scala code?
Edit: when re-compiling the code out of my reach and removing the type re-definition, everything works. So I think what I'm looking at is a way to "disable" an package-level type definition for a specific class.
Are you using a GUI (in particular Eclipse) to build your project?
This seems related to Scala trouble accessing Java methods (that has no answer but where the general consensus is that the problem is not with scala but with Eclipse).

Categories