Giter Site home page Giter Site logo

rjavaenv's Introduction

rJavaEnv: Java Environments for R Projects rJavaEnv website

Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public. Lifecycle: experimental CRAN status R-CMD-check pkgcheck codecov

DOI

The goal of rJavaEnv is to manage multiple Java JDKs in R projects by automating the process of downloading, installing, and configuring Java environments on a per-project basis. This package is inspired by the renv package for managing R environments in R projects.

You can request a specific Java Development Kit (JDK) in your project, and rJavaEnv will download and install the requested Java environment in a project-specific directory and set the PATH and JAVA_HOME for when you are using this project. Therefore, you can have different Java versions for different projects without contaminating your system with different Java versions.

WARNING This package is in the early stages of development and is not yet ready for production use. Please test it thoroughly before using it in your projects.

Install

You can install the development version of rJavaEnv from GitHub:

if (!requireNamespace("remotes", quietly = TRUE)) {
  install.packages("remotes")
}

remotes::install_github("e-kotov/rJavaEnv")

Simple Example

rJavaEnv::java_quick_install(version = 21)

This will:

  • download Java 21 distribution compatible with the current operating system and processor architecture into a local cache folder;

  • extract the downloaded Java distribution into another cache folder;

  • create a symbolic link (for macOS and Linux) or junction (for Windows, if that fails, just copies the files) rjavaenv/platform/processor_architecture/java_version in the current directory/project to point to the cached installation;

  • set the current session’s JAVA_HOME and PATH environment variables to point to the installed (symlinked) Java distribution;

  • add code to .Rprofile file in the current directory/project to set JAVA_HOME and PATH environment variables when the project is opened in RStudio.

After that, you can even remove rJavaEnv completely, as the Java environment will be set up in the project directory with the base R code that does not rely on rJavaEnv.

Functions Overview

The package has several core functions:

  1. java_quick_install()
    • Downloads, installs, and sets Java environment in the current working/project directory, all in one line of code.
  2. java_check_version_cmd()
    • Checks the installed Java version using terminal commands. For packages like opentripplanner, that performs Java calls using command line.
  3. java_version_check_rjava()
    • Checks the installed Java version using rJava in a separate R session. For rJava-dependent packages such as r5r.
  4. java_download()
    • Downloads a specified version and distribution of Java.
  5. java_install()
    • Installs a Java distribution file into current (or user-specified) project directory.
  6. java_env_set()
    • Sets the JAVA_HOME and PATH environment variables to a given path in current R session and/or in the .Rprofile file in the project directory.
  7. java_env_unset()
    • Remove the JAVA_HOME and PATH environment variables from the .Rpofile file in the project directory (but not in the current R session, please restart the session so that R picks up the system Java).
  8. java_list()
    • Lists all or some Java versions linked in the current project (or cached distributions or installations).
  9. java_clear()
    • Removes all or some Java versions linked in the current project (or cached distributions or installations).

See more details on all the functions in the Reference.

For detailed usage, see the Quick Start Vignette (work in progress).

Limitations

Currently, rJavaEnv only supports major Java versions such as 8, 11, 17, 21, 22. The download and install functions ignore the minor version of the Java distribution and just downloads the latest stable subversion of the specified major version. This is done to simplify the process and avoid the need to update the package every time a new minor version of Java is released. For most users this should be sufficient, but this is substandard for full reproducibility.

The main limitation is that if you want to switch to another Java environment, you will most likely have to restart the current R session and set the JAVA_HOME and PATH environment variables to the desired Java environment using rJavaEnv::java_env_set(). This cannot be done dynamically within the same R session due to the way Java is initialized in R, particularly with the rJava-dependent packages such as r5r. With packages like opentripplanner, that performs Java calls using command line, you can switch Java environments dynamically within the same R session as much as you want.

Therefore, if you need to use R packages that depend on different Java versions within the same project, you will have to create separate R scripts for each Java environment and run them in separate R sessions. One effective way of doing this is to use the callr package to run R scripts in separate R sessions. Another option is to use the targets package to manage the whole project workflow, which, as a side effect, will lead to all R scripts being run in separate R sessions. To use rJavaEnv with targets, you will need to download and install several Java environments using rJavaEnv::java_download() and rJavaEnv::java_install() and set the relevant path with rJavaEnv::java_env_set() at the beginning of each function that requires a certain Java version.

Future work

The future work includes:

  • Add support for more Java distributions and versions

  • Take care of R CMD javareconf

  • Possibly add support for specifying Java version beyond the major version

  • Possibly allow downloading several Java distributions in one function call, e.g. different major versions of the same ‘flavour’ or different ‘flavours’ of the same major version

  • Possibly add automation to get the Java that is required by specific Java-dependent R packages

I am open to suggestions and contributions, welcome to issues and pull requests.

Acknowledgements

I thank rOpenSci for the Dev Guide, as well as Hadley Wickham and Jennifer Bryan for the R Packages book.

Package hex sticker logo is partially generated by DALL-E by OpenAI. The logo also contains the original R logo.

Citation

To cite package ‘rJavaEnv’ in publications use:

Kotov E (2024). rJavaEnv: Java Environments for R Projects. doi:10.5281/zenodo.11403010 https://doi.org/10.5281/zenodo.11403010, https://github.com/e-kotov/rJavaEnv.

BibTeX:

@Manual{rjavaenv,
  title = {rJavaEnv: Java Environments for R Projects},
  author = {Egor Kotov},
  year = {2024},
  url = {https://github.com/e-kotov/rJavaEnv},
  doi = {10.5281/zenodo.11403010},
}

rjavaenv's People

Contributors

e-kotov avatar pachadotdev avatar

Stargazers

 avatar Eric Book avatar John Blischak avatar Marc Bosch avatar Santiago Mota avatar Robin Lovelace avatar  avatar

Watchers

 avatar

Forkers

pachadotdev

rjavaenv's Issues

new Java distributions

Consider which Java distributions should be supported and which should be installed by default. A good starting point for this is here https://whichjdk.com/ . The website also provides a nice summary and evaluation of the licensing terms of different distributions.

test coverage of at least 75%

https://devguide.ropensci.org/pkg_building.html#testing

To quote key relevant points from the guidelines:

  • All packages should have a test suite that covers major functionality of the package. The tests should also cover the behavior of the package in case of errors.

  • It is good practice to write unit tests for all functions, and all package code in general, ensuring key functionality is covered. Test coverage below 75% will likely require additional tests or explanation before being sent for review.

...

...

  • testthat has a function skip_on_cran() that you can use to not run tests on CRAN. We recommend using this on all functions that are API calls since they are quite likely to fail on CRAN. These tests should still run on continuous integration. Note that from testthat 3.1.2 skip_if_offline() automatically calls skip_on_cran(). More info on CRAN preparedness for API wrappers.

...

  • Even if you use continuous integration, we recommend that you run tests locally prior to submitting your package (you might need to set Sys.setenv(NOT_CRAN="true")).

need to install Java with rJavaEnv before installing rJava?

Consider the case when, say, a stock Rocker RStudio image is used. It has no Java. Or another clean system that does not have any version of any flavour of Java installed. In this case {rJava} may install, but will fail to load. See below.

install.packages("rJava")
#> Installing package into ‘/usr/local/lib/R/site-library’
#> (as ‘lib’ is unspecified)
#> trying URL 'https://p3m.dev/cran/__linux__/jammy/2024-06-13/src/contrib/rJava_1.0-11.tar.gz'
#> Content type 'binary/octet-stream' length 940665 bytes (918 KB)
#> ==================================================
#> downloaded 918 KB
#> 
#> * installing *binary* package ‘rJava’ ...
#> * DONE (rJava)
#> 
#> The downloaded source packages are in
#> 	‘/tmp/RtmpNw93ye/downloaded_packages’
library(rJava)
#> Error: package or namespace load failed for ‘rJava’:
#>  .onLoad failed in loadNamespace() for 'rJava', details:
#>   call: dyn.load(file, DLLpath = DLLpath, ...)
#>   error: unable to load shared object '/usr/local/lib/R/site-library/rJava/libs/rJava.so':
#>   libjvm.so: cannot open shared object file: No such file or directory

Therefore, if we install Java with:

rJavaEnv::java_quick_install(21)

We will get positive results for tools that call Java via command line:

> rJavaEnv::java_check_version_cmd()
JAVA_HOME: /home/rstudio/.cache/R/rJavaEnv/installed/linux/x64/21
Java path: /home/rstudio/.cache/R/rJavaEnv/installed/linux/x64/21/bin/java
Java version: "openjdk version \"21.0.3\" 2024-04-16 LTS OpenJDK Runtime Environment Corretto-21.0.3.9.1 (build 21.0.3+9-LTS) OpenJDK
64-Bit Server VM Corretto-21.0.3.9.1 (build 21.0.3+9-LTS, mixed mode, sharing)"
[1] TRUE

But rJava-dependent packages will fail:

> rJavaEnv::java_check_version_rjava()
✖ rJava package is not installed. You need to install rJava to use this function to check if rJava-based packages will work with the specified Java version.
[1] FALSE

But {rJava} cannot be installed and loaded successfully even after rJavaEnv::java_quick_install(21).

So in that case, do we need to address the #3 with rJavaEnv?

pkgcheck results - main

Checks for rJavaEnv (v0.0.0.9000)

git hash: 48669af6

  • ✔️ Package name is available
  • ✔️ has a 'codemeta.json' file.
  • ✖️ does not have a 'contributing' file.
  • ✖️ The following function has no documented return value: [java_check_version_rjava]
  • ✔️ uses 'roxygen2'.
  • ✔️ 'DESCRIPTION' has a URL field.
  • ✔️ 'DESCRIPTION' has a BugReports field.
  • ✔️ Package has at least one HTML vignette
  • ✖️ These functions do not have examples: [java_env_unset].
  • ✔️ Package has continuous integration checks.
  • ✖️ Package coverage is 0% (should be at least 75%).
  • ✔️ R CMD check found no errors.
  • ✔️ R CMD check found no warnings.

Important: All failing checks above must be addressed prior to proceeding

Package License: MIT + file LICENSE

try to address: cannot install rJava from source without javareconf with admin privileges

Test report for macOS (Apple Silicon/aarch64/ARM) (with R packages installed from source)

System:

sw_vers
#> ProductName: macOS
#> ProductVersion: 14.5
#> BuildVersion: 23F79

uname -m
#> arm64

Test sequence:

1. Install Homebrew from https://brew.sh/

2. Install R and RStudio

brew install r
brew install --cask rstudio

3. Check if there is Java in vanilla macOS

which java
#> /usr/bin/java

java --version
#> The operation couldn't be completed. Unable to locate a Java Runtime.
#> Please visit http://www.java.com for information on installing Java.

4. Run RStudio

5. Check if {rJava} can be installed with Java installed using {rJavaEnv}

install.packages("remotes")
remotes::install_github("e-kotov/rJavaEnv")
library(rJavaEnv)
java_quick_install(21)
java_check_version_cmd()

install.packages("rJava")

results in:

configure: error: Java Development Kit (JDK) is missing or not registered in R Make sure R is configured with full Java support (including JDK). Run
R CMD javareconf
as root to add Java support to R.
If you don't have root privileges, run
R CMD javareconf -e
to set all Java-related variables and then install rJava.
ERROR: configuration failed for package 'rJava'
* removing "/opt/homebrew/lib/R/4.4/site-library/rJava'
Warning in install.packages :
installation of package "rJava' had non-zero exit status

6. Try javareconf

In Terminal, without admin rights:

export JAVA_HOME=/Users/user/Library/Caches/org.R-project.R/R/rJavaEnv/installed/macos/aarch64/21
R CMD javareconf -e
install.packages("rJava")

Fails.

In Terminal, with admin rights:

export JAVA_HOME=/Users/user/Library/Caches/org.R-project.R/R/rJavaEnv/installed/macos/aarch64/21
R CMD javareconf
install.packages("rJava")

Succeeds! {rJava} is built from source!

Verdict

Overall, {rJavaEnv} package works as expected, but some manual actions are still required from the user. Specifically, the user needs to close R/RStudio and run two commands in the terminal with admin privileges to reconfigure Java.

Originally posted by @e-kotov in #15 (comment)

Setting a Java version globally

Hi @e-kotov , thanks for creating {rJavaEnv}! I tried the package and it was so simple and quick to use. A great contribution to the R community.

I noticed that the java_quick_install() functions sets a Java version in current working/project directory. Would it be possible to set a Java version globally?

I thought of perhaps including a parameter like java_quick_install(local = c(TRUE, FALSE)). This way, the user could choose to set a java version locally to a particular working/project directory (local = TRUE), OR to set a global version that would work for every project (local = FALSE). In the latter case, the advantage is that the user would need to call the java_quick_install() function only once.

consider the `R CMD javareconf `

"To configure R to point to the desired Java installation, use the R CMD javareconf command. " Source: https://solutions.posit.co/envs-pkgs/using-rjava/#reconfigure-r

How to address that in the package? Do we even care about that, as long as we are not compiling any Java software or Java-dependent packages from source? Is the package going to meet the needs of 99% of it's potential users without managing this R CMD javareconf issue, which will probably require R session restart to take effect?

submit to ROpenSci

Technical checks

Confirm each of the following by checking the box.

This package:

Release rJavaEnv 0.1.0

First release:

Prepare for release:

  • git pull
  • usethis::use_github_links()
  • urlchecker::url_check()
  • devtools::build_readme()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • git push
  • Draft blog post

Submit to CRAN:

  • usethis::use_version('minor')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted 🎉
  • Finish & publish blog post
  • Add link to blog post in pkgdown news menu
  • usethis::use_github_release()
  • usethis::use_dev_version(push = TRUE)
  • usethis::use_news_md()
  • Tweet

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.