Skip to content

problem packaging S4 class that contains a slot of jobjRef class

2 messages · Adrian Dragulescu, Simon Urbanek

#
Hello,

I'm trying to package some source files that link R to a broker using
a Java API and the rJava package.  I am successful doing the connection
and operate on it using my R code.  I would like to package the files and
release the package.

I created some S4 classes to hold several Java objects.  I use WinXP and R
2.7.1.  I've searched RSeek and the Wiki for help, but could not find a
solution.

Here is my class definition:
twsConnect <- function(...)
  new("twsConnect", ...)

setClass(
  Class="twsConnect",
  representation=representation(
    clientId    = "integer",
    host        = "character",
    port        = "integer",
    reference   = "jobjRef"),
  prototype=prototype(
    clientId    = as.integer(0),
    host        = "",
    port        = as.integer(7496),
    reference   = .jnull())
)

setMethod("initialize", "twsConnect", function(
  .Object, clientId = 0, host = "", port = 7496, ...)
  {
    # hook up to the TWS
    ref <- .jnew("dev/AAD_Trader", as.integer(clientId), host,
                 as.integer(port))

    if (class(ref)[1] != "jobjRef")
      stop("Could not connect.  Check your settings.")

    .Object at clientId <- as.integer(clientId)
    .Object at host <- as.character(host)
    .Object at port <- as.integer(port)
    .Object at reference <- ref

    .Object
  }
)


setMethod("show", "twsConnect",
  function(object){
    cat("Object of class \"", class(object), "\":\n", sep="")
    lines <- NULL
    for (s in slotNames(object)){
      cont  <- slot(object, s)
      if (is.character(cont))cont <- paste('"', cont, '"', sep="")
      if (class(cont)=="jobjRef") cont <- "jobjRef"
      lines <- paste(lines, paste(s, " = ", cont, "\n",
                                  sep=""), sep="")
    }
    cat(lines)
  }
)



I have other files too.  Here is the output from package creation:
S:\All\Risk\Software\R\R-2.7.1\bin>Rcmd build --force --binary
H:/user/R/Adrian/RIB/
* checking for file 'H:/user/R/Adrian/RIB/DESCRIPTION' ... OK
* preparing 'H:/user/R/Adrian/RIB':
* checking DESCRIPTION meta-information ... OK
* removing junk files
* excluding invalid files from 'RIB'
Subdirectory 'R' contains invalid file names:
  .make.IB.package.R .utilities.R
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
WARNING: directory 'RIB/inst/doc' is empty
* building binary distribution
WARNING: some HTML links may not be found
installing R.css in C:/DOCUME~1/e47187/LOCALS~1/Temp/Rinst238480883

Using auto-selected zip options ''

---------- Making package RIB ------------
  adding build stamp to DESCRIPTION
  installing NAMESPACE file and metadata
  installing R files
  installing inst files
  preparing package RIB for lazy loading
Loading required package: rJava
Warning: package 'rJava' was built under R version 2.7.2
Loading required package: zoo

Attaching package: 'zoo'


        The following object(s) are masked from package:base :

         as.Date.numeric

Creating a new generic function for "summary" in "RIB"
  installing man source files
  installing indices
  installing help
 >>> Building/Updating help pages for package 'RIB'
     Formats: text html latex example chm
  IBrokers-package                  text    html    latex   example chm
  reqAccountUpdates                 text    html    latex   example chm
  reqHistoricalData                 text    html    latex   example chm
  twsConnect                        text    html    latex   example chm
Note: removing empty section \details
Note: removing empty section \details
  twsContract                       text    html    latex   example chm
  twsOrder                          text    html    latex   example chm
hhc: not found
CHM compile failed: HTML Help Workshop not installed?
  adding MD5 sums

packaged installation of package 'RIB' as RIB_0.1.0.zip
* DONE (RIB)

Not clean yet, but good for testing.

So, from R:
Loading required package: RIB
Loading required package: rJava
Loading required package: zoo

Attaching package: 'zoo'


        The following object(s) are masked from package:base :

         as.Date.numeric

Warning message:
package 'rJava' was built under R version 2.7.2
Object of class "twsConnect":
clientId = 0
host = ""
port = 7496
reference = jobjRef
[1] "Java-Object<null>"
So I have no connection...
Error in initialize(value, ...) :
  cannot use object of class "numeric" in new():  class "twsConnect" does
not extend that class
but if I source the file:
Object of class "twsConnect":
clientId = 0
host = ""
port = 7496
reference = jobjRef
[1] "Java-Object{dev.AAD_Trader at 12558d6}"
Things work as I want, I have the connection.  What does source do, that I
miss when packaging?

My NAMESPACE file is:
exportPattern("^[^\\.]")

exportClasses("twsConnect", "twsContract", "twsExecutionFilter",
              "twsOrder")

exportMethods("show")

My .onLoad function contains ".jpackage(pkgname)".

I tried to package just the class twsConnect without the slot reference,
and things worked out fine.  I tried to say that twsConnect contains
"jobjRef" but did not have much success.


Thanks a lot,
Adrian Dragulescu
#
Adrian,

my guess would be that you're trying to crate some Java objects at the  
top level of your package. That won't work, because R stores a  
serialized image of created objects for efficiency and hence the  
reference to any Java objects that you create will disappear as soon  
as you're done installing the package. When you try to load the  
package you'll end up with null references for all objects you have  
attempted to create that way. You have two options to avoid that:

1) create objects at load time - i.e. in the initialization function  
after you have called .jpackage. Only then is Java up and running so  
you can safely create Java objects

2) [not recommended] use .jcache to serialize objects you want to keep  
at the top level after creating them. They will be then lazily  
deserialized after the package has been loaded. However, this requires  
all such classes to implement Serializable interface on the Java side  
and is conceptually not clean, because you have to be careful when  
your cached serialization goes out of sync with the actual object (see  
details in the documentation of .jcache).

This is just my guess based on the symptoms since I think you actually  
failed to send us the part of code that triggers the problem.

Cheers,
Simon
On Nov 6, 2008, at 10:04 , Adrian Dragulescu wrote: