Functional Java: importing from Maven - java

I have cloned a maven project on a new machine but I am having some problems with some of the dependencies as they don't seem to have been loaded.
One such case, is fj.Effect of Functional java. I am not sure if I am (manually) adding the right library.
In the code, I have:
private Effect<EventDBEvent> downloadEvent = new Effect<EventDBEvent>() {
#Override
public void e(EventDBEvent eventDBEvent) {
...
}
};
I have tried adding org.org.functionaljava:functionaljava-java8:4.32 and org.functionaljava:functionaljava:4.3 IntelliJ recognizes Effect but highlights the first line as error and says:
I have a similar issue in another line:
final ... = new ...(new Effect<Option<Integer>>() {
#Override
public void e(Option<Integer> integerOption) {
}
}, ...);
Type fj.Effect does not have type parameters.
Am I importing the wrong packages?
More generally, is there a way of knowing which packages I should use, based on an existing code?

The Effect class changed so that the arity is in the class name, e.g. Effect0, Effect1, etc., where the arity indicates the number of parameters to the method. You want to use the Effect1 class.

Related

Java inherited class in Scala results in Type mismatch error

I am new to Scala, so please bear any bloopers in my code. I'm trying to re-engineer some Scala code that has been given to me. When I'm trying to use Java inheritance, I get type mismatch; found error highlighted in eclipse.
I'm using sbt to generate eclipse artifacts and I'm able to import the project in eclipse.The code with the error is given below.
The interface:
public interface InnerClassGen {
static public interface IFactory {
InnerInter innerInt = null;
/** A String giving the canonical value of symbol. */
//# pure
Integer value();
#Override
String toString();
}
}
public class InnerClassImpl implements InnerClassGen {
static public class Node implements IFactory{
#Override
public Integer value() {
// TODO Auto-generated method stub
return null;
}
}
}
The relevant Scala file :
object SMTExprVisitor {
protected var NODE: InnerClassGen.IFactory = new InnerClassImpl.Node()
}
class SMTExprVisitor{
.....
}
I would like to know where I'm going wrong. Can someone also point me to relevant links if any?
In general, you should always consider only compilation errors produced by SBT (or scalac directly) as real ones. Due to complexity of the language, and limited integration with the compiler, Scala IDEs can both highlight code as having errors when it doesn't and fail to find errors which do exist.
Though Eclipse is supposed to be better at this than IDEA/Android Studio due to using the "presentation compiler" which extends the main Scala compiler, apparently you are still running into a case it doesn't handle.

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",
]
}
}

Gradle release build - preserving method parameter names

We are creating an Android library with an inner interface class. The problem we are facing is that the method parameter names are not preserved for interface class in the release build aar file. Although .aar file works fine, this creates problem in editor when using autocompletion, Implement methods etc. Please note that proguard is disabled.
public class Test {
public interface TestInterface {
void testCallback(int ordernumber, int vendorid);
}
public boolean init(Context context);
}
In the debug build, class is preserved fine. However, in the release build, parameter names of interface methods are not preserved. Interestingly it preserves parameter names of class methods. This I verified using decompiler.
public class Test {
public interface TestInterface {
void testCallback(int paramInt1, int paramInt2);
}
public boolean init(Context context);
}
I also tried setting debuggable flag in buildconfig without any help.
Will appreciate any help.
The official oracle docs state that interfaces do not preserve parameter names, so the only solution is including the docs with the library: Preserving parameter/argument names in compiled java classes

Groovy #Immutable classes in Java

I often recommend Groovy's #Immutable AST transformation as an easy way to make classes, well, immutable. This always works fine with other Groovy classes, but someone recently asked me if I could mix those classes into Java code. I always thought the answer was yes, but I'm hitting a snag.
Say I have an immutable User class:
import groovy.transform.Immutable
#Immutable
class User {
int id
String name
}
If I test this using a JUnit test written in Groovy, everything works as expected:
import org.junit.Test
class UserGroovyTest {
#Test
void testMapConstructor() {
assert new User(name: 'name', id: 3)
}
#Test
void testTupleConstructor() {
assert new User(3, 'name')
}
#Test
void testDefaultConstructor() {
assert new User()
}
#Test(expected = ReadOnlyPropertyException)
void testImmutableName() {
User u = new User(id: 3, name: 'name')
u.name = 'other'
}
}
I can do the same with a JUnit test written in Java:
import static org.junit.Assert.*;
import org.junit.Test;
public class UserJavaTest {
#Test
public void testDefaultCtor() {
assertNotNull(new User());
}
#Test
public void testTupleCtor() {
assertNotNull(new User(3, "name"));
}
#Test
public void testImmutableName() {
User u = new User(3, "name");
// u.setName("other") // Method not found; doesn't compile
}
}
This works, though there are troubles on the horizon. IntelliJ 15 doesn't like the call to new User(), claiming that constructor is not found. That also means the IDE underlines the class in red, meaning it has a compilation error. The test passes anyway, which is a bit strange, but so be it.
If I try to use the User class in Java code directly, things start getting weird.
public class UserDemo {
public static void main(String[] args) {
User user = new User();
System.out.println(user);
}
}
Again IntelliJ isn't happy, but compiles and runs. The output is, of all things:
User(0)
That's odd, because although the #Immutable transform does generate a toString method, I rather expected the output to show both properties. Still, that could be because the name property is null, so it's not included in the output.
If I try to use the tuple constructor:
public class UserDemo {
public static void main(String[] args) {
User user = new User(3, "name");
System.out.println(user);
}
}
I get
User(0, name)
as the output, at least this time (sometimes it doesn't work at all).
Then I added a Gradle build file. If I put the Groovy classes under src\main\groovy and the Java classes under src\main\java (same for the tests but using the test folder instead), I immediately get a compilation issue:
> gradle test
error: cannot find symbol
User user = new User(...)
^
I usually fix cross-compilation issues like this by trying to use the Groovy compiler for everything. If I put both classes under src\main\java, nothing changes, which isn't a big surprise. But if I put both classes under src\main\groovy, then I get this during the compileGroovy phase:
> gradle clean test
error: constructor in class User cannot be applied to the given types;
User user = new User(3, "name");
required: no arguments
found: int,String
reason: actual and formal arguments differ in length
Huh. This time it's objecting to the tuple constructor, because it thinks it only has a default constructor. I know the transform adds a default, a map-based, and a tuple constructor, but maybe they're not being generated in time for the Java code to see them.
Incidentally, if I separate the Java and Groovy classes again, and add the following to my Gradle build:
sourceSets {
main {
java { srcDirs = []}
groovy { srcDir 'src/main/java' }
}
}
I get the same error. If I don't add the sourceSets block, I get the User class not found error from earlier.
So the bottom line is, what's the correct way to add an #Immutable Groovy class to an existing Java system? Is there some way to get the constructors to be generated in time for Java to see them?
I've been making Groovy presentations to Java developers for years and saying you can do this, only to now run into problems. Please help me save face somehow. :)
I did try your scenario as well, where you have a single project with a src/main/java and a src/main/groovy directory and ended up with compilation errors similar to what you saw.
I was able to use Groovy immutable objects in Java when I put the Groovy immutables in a separate project from the Java code. I have created a simple example and pushed it to GitHub (https://github.com/cjstehno/immut).
Basically it's a Gradle multi-project with all the Groovy code (the immutable object) in the immut-groovy sub-project and all the Java code in the immut-java project. The immut-java project depends on the immut-groovy project and uses the immutable Something object:
public class SomethingFactory {
Something createSomething(int id, String label){
return new Something(id, label);
}
}
I added a unit test in the Java project which creates a new instance of the immutable Groovy class and verifies its contents.
public class SomethingFactoryTest {
#Test
public void createSomething(){
Something something = new SomethingFactory().createSomething(42, "wonderful");
assertEquals(something.getId(), 42);
assertEquals(something.getLabel(), "wonderful");
}
}
This is not really ideal, but it works.

Android app cannot install

While developing an app in AIDE for Android I have come across this error. The app would compile successfully but wouldn't install, reporting this error:
Could not run the App directly as root. Consider disabling direct running in the settings.
WARNING: linker: app_process has text relocations. This is wasting memory and is a security risk. Please fix.
pkg: /storage/sdcard/AppProjects/MyProgram/bin/MyProgram.apk
Failure [INSTALL_FAILED_DEXOPT]
exit with 0
I researched what could cause this and mainly came across reasons like "certificate error, try resigning the package" and "setting a permission twice in the manifest" and other stuff, none of which have worked.
Your problem: Java thinks you define two methods with the same signature.
Java method signature definition: https://docs.oracle.com/javase/tutorial/java/javaOO/methods.html
method declarations have six components, in order:
1.Modifiers—such as public, private, and others you will learn about later.
2.The return type—the data type of the value returned by the method, or void if the method does not return a value.
3.The method name—the rules for field names apply to method names as well, but the convention is a little different.
4.The parameter list in parenthesis—a comma-delimited list of input parameters, preceded by their data types, enclosed by parentheses, ().
If there are no parameters, you must use empty parentheses.
An exception list—to be discussed later.
The method body, enclosed between braces—the method's code, including the declaration of local variables, goes here.
As you can see above, the specification of generic classes is NOT part of the java method signature. Therefore java detects two add-methods with the same signature.
I found where the problem resides. It was in some code which looked very much like this:
public class Builder<T extends Base> {
private final List<Def1> subDefs1 = new ArrayList<>();
private final List<Def2> subDefs2 = new ArrayList<>();
public Builder<T> add(final Collection<Def1> ds) {
subDefs1.addAll(ds);
return this;
}
public Builder<T> add(final Collection<Def2> ds) {
subDefs2.addAll(ds);
return this;
}
}
interface Base {}
final class Def1 implements Base {}
final class Def2 implements Base {}
I had these add methods, which both take a Collection of some kind. The problem must be something to do with Java's lacklustre generics and the dexing process, I guess...

Categories