cannot add a jar to scala repl with the :cp command - scala

If I issue:
$ scala -classpath poi-3.9/poi-3.9-20121203.jar
scala> import org.apache.poi.hssf.usermodel.HSSFSheet
import org.apache.poi.hssf.usermodel.HSSFSheet
Everything works ok, but if instead I issue:
$ scala
scala> :cp poi-3.9/poi-3.9-20121203.jar
Added '/home/sas/tmp/poi/poi-3.9/poi-3.9-20121203.jar'. Your new classpath is:
".:/home/sas/tmp/poi/poi-3.9/poi-3.9-20121203.jar"
Nothing to replay.
scala> import org.apache.poi.hssf.usermodel.HSSFSheet
<console>:7: error: object apache is not a member of package org
import org.apache.poi.hssf.usermodel.HSSFSheet
^
Am I missing something?

No one seems to mention this but the correct solution is using the :require command:
scala> :require foo.jar
Added 'foo.jar' to classpath.

Another way to get jar files imported, in this case by default, is to add links in $SCALA_HOME/lib to the jar files of interest. Then every time you enter REPL, such linked jars will be uploaded.
For instance, for poi-3.9-20121203.jar, consider
(cd $SCALA_HOME/lib && ln -s full_path_to_poi_jar/poi-3.9-20121203.jar)

As noted in the comments, this is a known issue. You could use an alternative REPL implementation such as Ammonite.

Related

How do I make packages available to the Scala REPL?

I'm trying to get familiar with Scala. I am using macOS.
I've installed scala using brew install scala which is hassle-free and once complete I can launch the scala REPL simply by issuing scala and I'm at the scala> prompt.
I now want to import some packages, so I try:
import org.apache.spark.sql.Column
and unsurprisingly it fails with
error: object apache is not a member of package org
This makes sense, how would it know where to get that package from? Thing is, I don't know what I need to do to make that package available. Is there anything I can do from the command-line that would allow me to import org.apache.spark.sql.Column?
I have googled around a little but not found anything that explains in a jargon-free way. Complete Scala noob here so jargon-free responses would be appreciated.
Here are two ways to start a REPL with dependencies that I'm aware of:
Use SBT to manage dependencies, use console to start a REPL with those dependencies
Use Ammonite REPL
You could create a separate directory with a build.sbt where you set
scalaVersion := "2.11.12"
and then copy the
libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.3.0"
snippets from MavenCentral. Then you can run the REPL with sbt console. Note that this will create a project and target subdirectories, so it "leaves traces", you can't use it like the standalone scala-repl. You could also omit the build.sbt, and add the library-dependencies by typing them into the SBT-shell itself.
Alternatively you can just use Ammonite REPL that has been created exactly for that purpose.
You can use classpath to make the lib available i.e. download the jar locally and use the command as follows (here I'm using Apache IO lib to move files from scala prompt )
C0:Desktop pvangala$ scala -cp /Users/pvangala/Downloads/commons-io-2.6/commons-io-2.6.jar
Welcome to Scala 2.12.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_161).
Type in expressions for evaluation. Or try :help.
scala> import java.io.File
import java.io.File
scala> val src = new File("/Users/pvangala/Downloads/commons-io-2.6-bin.tar")
src: java.io.File = /Users/pvangala/Downloads/commons-io-2.6-bin.tar
scala> val dst = new File("/Users/pvangala/Desktop")
dst: java.io.File = /Users/pvangala/Desktop
scala> org.apache.commons.io.FileUtils.moveFileToDirectory(src, dst, true)
If you want to use spark stuff I'd recommend you use the spark-shell that comes with the spark-installation. I don't know macOS so I can't help you much with the install of Spark there.
For normal Scala I recommend ammonite http://ammonite.io/#Ammonite-REPL that has included syntax to allow to pull packages/dependencies.
If you want to use spark, you should use the spark-shell instead the scala REPL. It has almost the same behaviour but includes all the spark dependencies by default.
You should download spark binaries from here
Then if you are using Linux, you should create the variable SPARK_HOME pointing to the downloaded folder and include its bin folder in PATH.
then you can start it in any console with the command spark-shell
In Windows i'm not sure, but i think that you should have a spark-shell.cmd file or something similar which you can use to start the spark-shell,
I did the following in Windows:
for /f "tokens=*" %%a in ('java -jar coursier fetch -p "com.lihaoyi::requests:0.2.0" "com.lihaoyi::upickle:0.7.5"') do set SCP=%%a
scala -nc -classpath %SCP% %1 %2 %3
Instead of the two libraries listed here you can use an unlimited number of other libraries you need. They must be available in maven central, though. The %1 could be a scala script (".sc" extension). But you could leave it empty and the REPL will start with the libraries on the classpath.

Scala REPL additional Jars

I am adding jars into my scala repl like so:
scala> :cp scalaj-http_2.10-2.2.1.jar
Added '/home/XXX/scalaj-http_2.10-2.2.1.jar'. Your new classpath is:
".:/home/XXX/json4s-native_2.10-3.3.0.RC3.jar:/home/XXX/scalaj-http_2.10-2.2.1.jar"
Nothing to replay.
Now when I try and import that jar for use I get an error:
scala> import scalaj.http._
<console>:7: error: not found: value scalaj
import scalaj.http._
I've tried this on another jar:
scala> :cp json4s-native_2.10-3.3.0.RC3.jar
Added '/home/XXX/json4s-native_2.10-3.3.0.RC3.jar'. Your new classpath is:
".:/home/XXX/json4s-native_2.10-3.3.0.RC3.jar"
Nothing to replay.
scala> import org.json4s.JsonDSL._
<console>:7: error: object json4s is not a member of package org
import org.json4s.JsonDSL._
I've read multuple tutorials online that all do it this way but my REPL does not seem to be behaving in the same manor.
I am using Scala 2.10
Double check your path, if it still is not working you can try adding the jar at the time you start the REPL (it's always seemed to work for me, even with v2.10)
scala -cp /home/XXX/json4s-native_2.10-3.3.0.RC3.jar:/home/XXX/scalaj-http_2.10-2.2.1.jar
Note: That the delimeter between jars is ; for Windows and : otherwise.

Making jar files available to the scala REPL

I can't seem to get this to work, so i have tried what's probably the most straightforward case--ie, retrieve the jar file and into a given directory then start the scala REPL from that directory--still no luck.
I know the jar files are fine and correctly references (eg, i can access them from project directories via eclipse/scala ide)
I also know that my import statements (one is shown below) are valid.
cd ~/my_scala_jars
retrieve the artifact from the maven repo
wget -q -nd -np -r \
http://repo1.maven.org/maven2/org/scalaz/scalaz-core_2.12.0-M1/7.1.2/scalaz-core_2.12.0-M1-7.1.2.jar
start the scala REPL and add the jar to the REPL classpath:
scala -cp scalaz-core_2.12.0-M1-7.1.2.jar
scala> import scalaz.stream.io
<console>:7: error: object stream is not a member of package scalaz
import scalaz.stream.io
in case it's useful, trying this with different jars (that i downloaded as i showed with scalaz above) will sometimes cause the REPL to throw a not found error instead
scala> import breeze.linalg._
<console>:7: error: not found: value breeze
import breeze.linalg._
it seems to me that the REPL should recognize these jars because the directory has been added to my CLASSPATH, but also because i believe the current directory is also added to the classpath (at least during the REPL session)--and still both fail.
I am not sure why the jar files are not picked up as I haven't really tried to do that. What I do, and find useful, is to create a number of build.sbt files for specific purposes, e.g. for working with a specific suite of libraries at a REPL.
If you do this, and then launch a REPL using the command sbt console, from the directory containing the appropriate build.sbt, then you can have a console with the libraries you want available on the classpath to that console.
This might not be ideal, but it does work and I find it quite useful.

Scala : trying to get log4j working

Scala newb here (it's my 2nd day of using it). I want to get log4j logging working in my Scala script. The script and the results are below, any ideas as to what's going wrong?
[sean#ibmp2 pybackup]$ cat backup.scala
import org.apache.log4j._
val log = LogFactory.getLog()
log.info("started backup")
[sean#ibmp2 pybackup]$ scala -cp log4j-1.2.16.jar:. backup.scala
/home/sean/projects/personal/pybackup/backup.scala:1: error: value apache is not a member of package org
import org.apache.log4j._
^
one error found
I reproduce it under Windows: delimiter of '-classpath' must be ';' there (not ':'). Are you use cygwin or some sort of unix emulator?
But Scala script works anywhere without current dir in classpath. Try to use:
$ scala -cp log4j-1.2.16.jar backup.scala
JFI: LogFactory is a class of slf4j library (not log4j).
UPDATE
Another possible case: broken jar in classpath, maybe during download or something else. Scala interpreter does report only about unavailable member of the package.
$ echo "qwerty" > example.jar
$ scala -cp example.jar backup.scala
backup.scala:1: error: value apache is not a member of package org
...
Need to inspect content of the jar-file:
$ jar -tf log4j-1.2.16.jar
...
org/apache/log4j/Appender.class
...
Did you remember to put log4j.jar in your classpath?
Had Similar issue when started doing Scala Development using Eclipse, doing a clean build solved the problem.
Guess the Scala tools are not matured et.
Instead of using log4j directly, you might try using Configgy. It's the Scala Way™ to work with log4j, as well as configuration files. It also plays nicely with SBT and Maven.
I asked and answered this question myself, have a look:
Put it under src/main/resources/logback.xml. It will be copied to the right location when SBT is doing the artifact assembly.

"is not a member of package" error when importing package in Scala with SBT

(Relative beginner here, please be gentle...)
I've got a Scala program that I can build with sbt. I can (from within sbt) run compile and test-compile with no errors. I've defined a package by putting package com.mycompany.mypackagename at the top of several .scala files. When I do console to get a Scala REPL, this happens:
scala> import com.mycompany.mypackagename._
<console>:5: error: value mypackagename is not a member of package com.mycompany
import com.mycompany.mypackagename._
Any variation of this also fails. When I just do import com.mycompany I get no problems.
I thought that running the Scala console from within sbt would properly set the classpath based on the current projects? What (completely obvious) thing am I missing?
I ran into this same problem, and then I realized I was running scala 2.10.0 on commandline, and IDEA was using Scala 2.9.2. So the fix was to change both to use the same version, and:
sbt clean
What will happen if you import actual class name instead of wildcard.
import com.mycompany.mypackagename.ActualClassName