Can't get path to resource - scala

I am trying to use Scala macro annotations with this library.
I have a schema file at src/main/resources/avsc/FriendRequestAcceptedGson.avsc
I am trying to refer to it in my code as follows:
#AvroTypeProvider("/avsc/FriendRequestAcceptedGson.avsc")
#AvroRecord
case class FriendRequestAcceptedGson()
This is the error I get:
[error] /home/lee/Code/bigdata-friends/java/etl/src/main/scala/com/mxit/bd/friends/etl/Runner.scala:64: exception during macro expansion:
[error] java.io.FileNotFoundException: /avsc/FriendRequestAcceptedGson.avsc (No such file or directory)
[error] at java.io.FileInputStream.open(Native Method)
[error] at java.io.FileInputStream.<init>(FileInputStream.java:146)
[error] at org.codehaus.jackson.JsonFactory.createJsonParser(JsonFactory.java:504)
[error] at org.apache.avro.Schema$Parser.parse(Schema.java:922)
[error] at com.julianpeeters.avro.annotations.util.SchemaParser$.getSchema(SchemaParser.scala:20)
[error] at com.julianpeeters.avro.annotations.AvroTypeProviderMacro$.impl(TypeProviderMacro.scala:23)
[error] #AvroTypeProvider("/avsc/FriendRequestAcceptedGson.avsc")

Resources are compiled into your JAR file. You must find them with a ClassLoader, not in the file system. The java.io.FIle class only knows how to look in the file system. Now, if you're trying to open the source file (which may not be present when the JAR is deployed), it will depend on where your current working directory is relative to the file. Probably it is at the root so the path you need to use is the full relative one: src/main/resources/avsc/FriendRequestAcceptedGson.avsc

Related

sbt / native-packager, new jdeps error: java.lang.module.FindException: Module java.activation not found, required by java.xml.bind

I have not changed my setup as far as I can see. As of today, trying to run sbt native packager with jlink gives this error:
[info] Running: jdeps --multi-release 11 -R ...
[error] Exception in thread "main" java.lang.module.FindException: Module java.activation not found, required by java.xml.bind
[error] at java.base/java.lang.module.Resolver.findFail(Resolver.java:877)
[error] at java.base/java.lang.module.Resolver.resolve(Resolver.java:191)
[error] at java.base/java.lang.module.Resolver.resolve(Resolver.java:140)
[error] at java.base/java.lang.module.Configuration.resolve(Configuration.java:422)
[error] at java.base/java.lang.module.Configuration.resolve(Configuration.java:256)
[error] at jdk.jdeps/com.sun.tools.jdeps.JdepsConfiguration$Builder.build(JdepsConfiguration.java:564)
[error] at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.buildConfig(JdepsTask.java:603)
[error] at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:557)
[error] at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:533)
[error] at jdk.jdeps/com.sun.tools.jdeps.Main.run(Main.java:64)
[error] at jdk.jdeps/com.sun.tools.jdeps.Main$JDepsToolProvider.run(Main.java:73)
[error] at java.base/java.util.spi.ToolProvider.run(ToolProvider.java:137)
[error] at ru.eldis.toollauncher.ToolLauncher.runTool(ToolLauncher.java:68)
[error] at ru.eldis.toollauncher.ToolLauncher.lambda$main$1(ToolLauncher.java:33)
[error] at ru.eldis.toollauncher.ToolLauncher.main(ToolLauncher.java:48)
How do I fix this? I tried adding javax.activation to libraryDependencies, that doesn't seem to have any effect or anything to do with this problem.
Edit: The root problem of seems to be my dependency on Pi4j 1.4, which depends on javax.xml.bind:jaxb-api which in turn depends on javax.activation:javax.activation-api. Now I don't understand much of this Java module stuff, but javax.activation-api does exist on Maven, so why does jdeps complain? If I exclude javax.xml.bind, it works, but now I'm worried I'm actually missing stuff on the class path.
javax.activation has been removed since java 11.
To fix it you can:
Download the javax.activation jar and run the command by adding this jar on module path:
jdeps --multi-release 11 -R --module-path path\to\javax.activation.jar ...
Running this command with java 8 jdeps

sbt: How can I add a local filesystem jar to my project...but also a lot of .so libraries?

In this question, there is discussion of how to include jar file into an sbt project. I need both a .jar file and some .so library files.
Attempt 1:
I can move the jar file into my sbt lib/ directory, which is great, except that this application has a small jar which is just a wrapper around C++ software. The stuff I want to do is in the .so library files, and if I move the jar file to ./lib by itself, I get linking errors:
sbt:SimpleProject> run linearSalience
[info] Running linearSalience linearSalience
[error] (run-main-0) java.lang.UnsatisfiedLinkError: no java_salience in java.library.path
[error] java.lang.UnsatisfiedLinkError: no java_salience in java.library.path
[error] at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
Attempt 2:
I have tried putting simlinks to the desired libraries into the lib/ folder, but that didn't work. I don't want to copy the entire library into the lib/ folder, even if that would work, since it is almost 2 GB; and it would be silly to copy it for each project.
Attempt 3:
I tried setting java.library.path through the javaOptions of sbt, by adding the following line to build.sbt
javaOptions in run += "-Djava.library.path=/opt/path/to/lib/:/opt/path/to/sdk/java/src/"
The first path contains the .so files, the second the .jar file. In this case, the compiler couldn't even find the packages (which was not a problem while the .jar file was in the lib/ folder of sbt):
[info] Compiling 1 Scala source to /opt/optests/sbttest/target/scala-2.10/classes ...
[error] /opt/optests/sbttest/src/main/scala/SimpleApp.scala:6:12: object lexalytics is not a member of package com
[error] import com.lexalytics.salience.{Salience, Section, Sentence, Word}
[error] ^
[error] /opt/optests/sbttest/src/main/scala/SimpleApp.scala:23:23: not found: type Salience
[error] val session = new Salience("/opt/path/to/license.v5", "/opt/path/to/data")
[error] ^
...etc
Attempt 4:
I try to set the LD_LIBRARY_PATH environment variable (as suggested here)
[user#server ~]$ echo $LD_LIBRARY_PATH
/opt/path/to/lib/:/opt/path/to/sdk/java/src/
The result is the same error as in 3
It seems like all the questions on this topic are resolved by either putting single jar files into lib/ or using managed dependencies (as here). But I have a local-only repository with no online support, that is more than a single .jar file.
Ultimately, I need to get the library directory into java.library.path, but how do I do that?
Note: This is not a duplicate of any question that deals with only .jar files and has no mention of .so files.
When you use a JNI wrapper over a native library on JVM (it doesn't matter on the language, it can be Java or Scala), the library jar file usually contains only the JNI glue code, defining how to map some java api calls to the native library calls. This jar is just a regular library, so it can be dropped to the /lib sbt folder as usual.
The native library itself should be present at runtime within the java.library.path, so you were quite close. As you suggested, you can add native SDK to the javaOptions in run (along with the jar in /lib folder) and it should work.

Executing sbt run in current project with ensime emacs

I have a Scala project called scala-playground and I generated the configuration for Ensime with sbt ensimeConfig and sbt ensimeConfigProject.
When running M-x ensime from a buffer of the project, I can see in the Emacs statusbar that Ensime is connected: it displays Scala[scala-playground].
When running the project with C-c C-b r, a new sbt instance is started in the home directory, a directory in $HOME/project is created and instead of the project directory and fails:
[info] Loading project definition from /home/user/project
[info] Set current project to user (in build file:/home/user/)
[info] sbt server started at 127.0.0.1:4766
sbt:user>
sbt:user> run
[error] java.lang.RuntimeException: No main class detected.
[error] at scala.sys.package$.error(package.scala:27)
[error] at sbt.Defaults$.$anonfun$runTask$4(Defaults.scala:1199)
[error] at scala.Option.getOrElse(Option.scala:121)
[error] at sbt.Defaults$.$anonfun$runTask$3(Defaults.scala:1199)
[error] at sbt.Defaults$.$anonfun$runTask$3$adapted(Defaults.scala:1198)
[error] at scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:42)
[error] at sbt.std.Transform$$anon$4.work(System.scala:64)
[error] at sbt.Execute.$anonfun$submit$2(Execute.scala:257)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
[error] at sbt.Execute.work(Execute.scala:266)
[error] at sbt.Execute.$anonfun$submit$1(Execute.scala:257)
[error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:167)
[error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:32)
[error] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] at java.lang.Thread.run(Thread.java:748)
[error] (compile:run) No main class detected.
[error] Total time: 0 s, completed Aug 28, 2017 9:10:03 PM
What is going on?
Short story
Remove ~/project folder and then start emacs.
Long story
If you ever run sbt in your $HOME directory it created basic project structure there, mainly project and target directory. And then if you open any *.scala file emacs (sbt-mode) will go up your path to find root project directory. And it finds one in your $HOME. You can see it in doc's:
Starting from the current default-directory, find a parent
directory that is an sbt root. An sbt root directory is
identified by the following rules:
- a directory containing a 'project/build.properties' in it.
- a directory that contains a file matching one of the patterns
'*.sbt' or 'project/*.scala' file in it.
One problem with current implementation is fact that this process will be done only once per buffer. If sbt:buffer-project-root variable is set once it will be not updated.
You can force a new value either by restarting emacs, or by evaluating (setq-local sbt:buffer-project-root nil) per each opened buffer, and then starting sbt form emacs in the usual way.
If you remove ~/project and run ensime-sbt from any buffer with sbt:buffer-project-root with wrong value, it will start sbt in home, which creates ~/project again. So again, the easiest way is to kill emacs, remove the directory, and then start emacs again.

org.mockito.internal.matchers.LocalizedMatcher cannot be cast to org.mockito.ArgumentMatcher with "any" matcher when running "activator test"

I'm having an error in one of my specs2 tests. The project is implemented with Play!Framework (Scala).
This is my test:
class AmazonEmailSenderSpec extends Specification with Mockito {
"AmazonEmailSenderSpec#sendEmail" should {
"Send Email with correct data" in {
val client = mock[AmazonSimpleEmailServiceAsyncClient]
val emailSender = new AmazonEmailSender(client)
emailSender.sendEmail(Email(subject, content, from, to, cc))
val captor = ArgumentCaptor.forClass(classOf[SendEmailRequest])
there was one(client).sendEmail(captor.capture)
val sendEmailRequest: SendEmailRequest = captor.getValue
}
}
}
This test works fine if I run it on intellij, but somehow, it fails when I run it on the console using the play activator:
activator test
I get:
[info] AmazonEmailSenderSpec#sendEmail should
[error] ! Send Email with correct data
[error] org.mockito.internal.matchers.LocalizedMatcher cannot be cast to org.mockito.ArgumentMatcher (ArgumentsComparator.java:25)
[error] org.mockito.internal.invocation.ArgumentsComparator.argumentsMatch(ArgumentsComparator.java:25)
[error] org.mockito.internal.invocation.ArgumentsComparator.argumentsMatch(ArgumentsComparator.java:17)
[error] org.mockito.internal.invocation.InvocationMatcher.matches(InvocationMatcher.java:56)
[error] org.mockito.internal.invocation.InvocationsFinder$RemoveNotMatching.isOut(InvocationsFinder.java:145)
[error] org.mockito.internal.invocation.InvocationsFinder$RemoveNotMatching.isOut(InvocationsFinder.java:137)
[error] org.mockito.internal.util.collections.ListUtil.filter(ListUtil.java:16)
[error] org.mockito.internal.invocation.InvocationsFinder.findInvocations(InvocationsFinder.java:20)
[error] org.mockito.internal.verification.checkers.MissingInvocationChecker.check(MissingInvocationChecker.java:32)
[error] org.mockito.internal.verification.Times.verify(Times.java:36)
[error] org.mockito.internal.verification.MockAwareVerificationMode.verify(MockAwareVerificationMode.java:21)
[error] org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:76)
[error] org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
[error] org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:37)
[error] org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:36)
[error] org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.access$000(MockMethodInterceptor.java:17)
[error] org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptSuperCallable(MockMethodInterceptor.java:96)
[error] com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceAsyncClient$MockitoMock$1778874818.sendEmail(Unknown Source)
[error] integration.email.AmazonEmailSenderSpec$$anonfun$1$$anonfun$apply$11$$anonfun$apply$12.apply(AmazonEmailSenderSpec.scala:27)
[error] integration.email.AmazonEmailSenderSpec$$anonfun$1$$anonfun$apply$11$$anonfun$apply$12.apply(AmazonEmailSenderSpec.scala:27)
[error] integration.email.AmazonEmailSenderSpec$$anonfun$1$$anonfun$apply$11.apply(AmazonEmailSenderSpec.scala:27)
[error] integration.email.AmazonEmailSenderSpec$$anonfun$1$$anonfun$apply$11.apply(AmazonEmailSenderSpec.scala:19)
I can't understand why a LocalizedMatcher is being used by activator when an ArgumentMatcher should be used instead.
The signature to the method I'm trying to match is:
public SendEmailResult sendEmail(SendEmailRequest sendEmailRequest)
Couldn't really find any hints on google. Any ideas? Am I missing something really silly?
This is an old question, but I just happened to run into the same issue in 2017:
A solution that worked for me (JUnit/Specs2, in a mixed Java/Scala) project:
I forced mockito to use the latest version 2.7.11. But I also had a dependency on org.specs2:specs2-mock_2.12:3.8.6 which is still based on mockito 1.9.5. See maven central.
Somewhere here lies the problem. I removed the dependency on specs2-mock and Specs2's mockito syntax sugar and replaced it with plain mockito code. Voila! The error mentioned above was gone.

Using Play 2.4 with a renamed `conf/routes` file

My simple Play 2.4 project does not compile when I rename the conf/routes file to something else, e.g. conf/hello.routes. The reason I'm doing this is to enable composition of APIs while allowing them to be developed in separate git repositories and sbt projects.
The idea of multiproject support is based on this project and blog post - but that's using Play 2.3.
The error I get is:
$ sbt test
...
[info] Hello should
[error] ! give {hello: true}
[error] Unable to provision, see the following errors:
[error]
[error] 1) Error in custom provider, java.lang.ClassCastException: interface play.api.routing.Router is not assignable from class hello.routes
[error] while locating play.api.test.FakeRouterProvider
[error] while locating play.api.routing.Router
[error]
[error] 1 error (InjectorImpl.java:1025)
[error] com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1025)
[error] com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
[error] play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:321)
[error] play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:316)
...
Got this resolved (code in the git repo now works).
The problems were likely connected to both of these:
the Controller implementation wants to be within a package controllers.hello instead of just hello
in the application.conf file one should omit the controllers namespace, i.e.
play.http.router = app.Routes
I learned this simply by comparing this code with samples that work.