Rstudio Connect Shiny dashboard only shows plot if table is visible - r

I want to have a Shiny dashboard on Rstudio Connect where data is read from my companies data store via JDBC, and then plotted. Ultimately the user would be able to give some parameters and the appropriate output would be displayed.
What I've discovered is that if I show a table of the data and the plot, everything works out fine. However, if I do not display the table I get an error:
Error: An error has occurred. Check your logs or contact the app author for clarification.
The line in the log files related to the error is not meaningful to me, but appears to be java related (and so maybe related to the JDBC connection):
Warning: Error in .jcheck: Java Exception <no description because toString() failed>
.jcall(conn#jc, "Ljava/sql/Statement;", "createStatement")
new("jobjRef", jobj = <pointer: 0x55cbc9a35608>, jclass = "java/lang/Throwable")
What works?
Here's as minimum a reproducible example as I could get. I appreciate that the architecture is internal to my company, so it won't run for others, but I think it can be helpful. The below code works:
# app.R
library(RJDBC)
library(shiny)
getconnection <- function(){
ORACLE_JAR <- '/usr/lib/oracle/21/client64/lib/ojdbc8.jar'
db_host = "db_host.company.information:1521"
drv <- RJDBC::JDBC("oracle.jdbc.OracleDriver",
ORACLE_JAR,
identifier.quote="`")
sid <- "sid.prd.tns"
url <- paste("jdbc:oracle:thin:#/",
db_host,
sid, sep = '/')
connection<-dbConnect(drv,
url,
user='****', # anonymised for stack overflow
password='****',
believeNRows=FALSE )
return(connection)
}
ui <- fluidPage(
titlePanel("MinRepEx"),
tableOutput('result'),
plotOutput('plot')
)
server <- function(input, output) {
conn <- getconnection()
mydata <- reactive({query_result(conn)})
output$result <- renderTable(head(mydata()))
output$result <- NULL
myplot <- reactive({plot(OBS_VALUE ~ OBS_DATE, data = mydata())})
output$plot <-renderPlot({myplot()})
}
shinyApp(ui = ui, server = server)
When I deploy this, as I say it works:
What doesn't work?
If I remove the lines related to result, i.e. the table output things stop working:
## Everyhing above this line is kept unchanged
ui <- fluidPage(
titlePanel("MinRepEx"),
# tableOutput('result'),
plotOutput('plot')
)
server <- function(input, output) {
conn <- getconnection()
mydata <- reactive({query_result(conn)})
# output$result <- renderTable(head(mydata()))
myplot <- reactive({plot(OBS_VALUE ~ OBS_DATE, data = mydata())})
output$plot <-renderPlot({myplot()})
}
shinyApp(ui = ui, server = server)
which leads to:
Possible solutions that need tweeking:
The code works as intended on my machine it does not work when I ship it to RStudio Connect.
The code is a minimised version of the code where there is a need for query_result to be a reactive function, so I can't take it out of the reactive world. However, if I do, I can display the chart on its own. `
Likewise, if I open the connection conn inside mydata it will generate the image. However opening the connection each time is very slow. If there was someway to check if a connection was open and if not open one, or to make the connection visible inside mydata?
What else have I tried?
I've tried a few other things that might help inform about the solution:
If I just do renderTable, there are no problems (except that I do't have the chart I want).
If I change the order of plotOutput and tableOutput in the UI, the table and plot appear
If I change the order of renderTable and renderPlot in the server, neither table nor plot are produced and I have the same error message in the logs twice.
If I introduce a Sys.sleep(60) command to myplot, it doesn't fix the issue
I have put a the line data <- mydata() inside the renderPlot({...}) before myplot()
The above 'possible solutions' might yield something, but rather frustratingly, I would like to know why the connection remains visible if I show the table or the table and plot, but not the plot on its own. Likewise, the code works without this issue locally, but not remotely. It would be interesting to understand why.

Related

R: Data Frame launching manually works well, in shiny is incomplete

I webscraped 2 tables (A and B). Then I merge them by rows (rbind). When I launch it, everything is ok. When I wanna use it in shiny app there is something wrong. Below structure of tables and what shiny shows. Any suggestion? Where could be the problem? Unfortunatelly, I can not show the code, because this is for my thesis. I would be very grateful for your help.
As you can see the problem is with third column. B table has all rows with NA. After merge, all data from A table has also NA.
In shiny table is showed by renderTable.
Structure of tables A and B
I have no answer for your question, but I would like to write something and there is not enough space for this in comment section, so I will write this as answer and eventually delete later. So - I rather believe that there is something wrong with your code which you use inside shiny and would like to check this with your help. I assume you need some help with debugging, so I will post a code below:
library(shiny)
ui <- fluidPage(
tableOutput("table")
)
server <- function(input, output, session) {
my_df <- reactive({
data.frame(a = c(1, 2, 3),
b = c(4, 5, 6))
})
output$table <- renderTable({
my_df()
browser()
})
}
shinyApp(ui, server)
In the code above I have made one output (table output) and - on the server side in reactive - I'm creating data.frame. Then I use this reactive function inside my output (output$plot). However, the last line inside output$plot is function browser() which is used for debugging. You can try my code in your console and see that when you run shiny app, it immediately moving back to console (but this is "dubugging state", so console looks a little different, for example there is a button "stop" with red square which can be use to close debugging state). Please run my shiny app and when you will be back in the console, in the debugging state, type my_df() to see the data.frame object. Could you please do the same with your shiny app? I mean, could you use browser() function on the last line in your renderTable? And come back and tell if the last column contains only NA or not when displayed in the console? If not, then I would say that you are doing something different in Shiny than manually with your tables.

Shiny - How to test fileInput()

I'm trying to write tests in order to check if a shiny function fileInput() is reading files correctly.
My problem is that I don't know what to write in session$setInputs() in order to grab the file from my system.
Here is an example app:
library(shiny)
ui <- fluidPage(
tagList(
fileInput("file", "Please upload a file"),
tableOutput("text")
)
)
server <- function(input, output, session){
file <- reactive({input$file})
output$text <- renderTable({
req(file())
read.csv(file()$datapath)
})
}
shinyApp(ui, server)
Now, I want to be able to use testServer() in order to set a file address and see if my app loads it correctly, but I can't figure out how to do it:
address <- "path/to/text.csv"
testServer(server, {
session$setInputs(file = address)
print(file())
})
I think it has to do with the fact that fileInput() uploads the file to a temp folder and returns to shiny a dataframe where you can get the datapath, but I'm unable to simulate this pass in order to make the test work
I have the same question as you do, I did some investigating and could not find any way of testing fileInput with testServer or testthat. The best solution that I found was testing fileInput by taking a snapshot when recording a test with recordTest() of the shinytest package.
Sorry for answering this late.
I asked the same question at rstudio's forums and got an answer here
The basics of it are setting the file's datapath as a list:
address <- "path/to/text.csv"
testServer(server, { session$setInputs(file= list(datapath = address)) })

Replacing accents in R/Shiny

My problem relates to translation of accented characters in R/Shiny - I tried to employ the solution discussed here but ran into a frustrating exception:
Within RStudio; if I highlight all lines of the code below and then press Ctrl+Enter (Run-Selected-Lines) I get the expected output of "ooo".
However if I press 'Run App' (as part of a project) I instead get "ǒoo" - i.e. the first character doesn't get mapped.
library(shiny)
ui <- fluidPage()
server <- function(input, output) {
charactermap = list('ǒ'='o', 'ô'='o', 'ø'='o')
removeaccents <- function(x) {
corrected <- chartr(paste(names(charactermap), collapse=''),
paste(charactermap, collapse=''),
x)
return(corrected)
}
print(removeaccents("ǒôø"))
}
# Run the application
shinyApp(ui = ui, server = server)
This seems to happen with only a small number of characters I am interested in - any ideas why this may be happening and how to fix it please???

ggplot histogram fails inside shiny app

I am trying to plot a simple histogram inside a shiny app. Outside the app (in R script), the graph gets plotted without any problems, (see here) but the same code produces an odd looking graph from inside the app (see the wrong graph here)
Could you help me figure out what's wrong? Link to dataset: https://drive.google.com/open?id=1ITK0lTWm_mkb9KonHLq4nuKDv-PBUDeR
library(ggplot2)
library(ggthemes)
library(scales)
library(shiny)
# read data
cso_corruption <- read.csv("cso_corruption.csv", header = T, sep = ",")
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
radioButtons(inputId = "x",label ="Measurement Type",choices =
c("freq_business", "freq_cso"), selected = NULL)
),
mainPanel(
plotOutput(outputId = "hist")
)
)
)
server <- function(input, output) {
output$hist <- renderPlot(ggplot(data = na.omit(cso_corruption), aes(x=input$x)) +
geom_histogram(fill="lightgreen", stat="count"))
}
shinyApp(ui = ui, server = server)
Possible reason is the data is not making it into the server.
I would put the csv into another file within the directory, so you can access it using
read.csv("./Data/projectdata.csv")
Therefore it does not get lost when you publish. Also make sure the data is checked when publishing. One last note to include the read.csv function in the server.
After many trial-and-errors, I have figured out a solution. The trick is, in the server, I used aes_string instead of aes. I haven't figured out why aes_string works here, since it is supposed to require the variables to be passed in quotes. But it works for some reason.

Create R Shiny app with dynamic RJDBC connection

I would like to find a similar function to reactiveFileReaderfunction from R Shiny pacakge to dynamically read data from an Oracle database using RJDBC driver.
Please find an example below to explain my issue:
Suppose my_data.csv is a extraction of my MY_ORACLE_TABLE (which is hosted on my oracle database).
In the first case below, when I manualy change the values of my_data.csv, my Shiny app automaticaly updates:
server <- function(input, output) {
output$table1 <- DT::renderDataTable({
reactiveFileReader(1000,session = NULL,filePath = "my_data.csv",readFunc = read.csv2)()
})
}
But in the second case below, supposing MY_ORACLE_TABLE updates, I have to reload my Shiny app URL to make the display update:
server <- function(input, output) {
output$table1 <- DT::renderDataTable({
reactive({dbGetQuery(con, "SELECT * FROM MY_ORACLE_TABLE})()
})
}
Any tips ?
The problem is that
dbGetQuery(con, "SELECT * FROM MY_ORACLE_TABLE")
does not depend on any reactive context and will not automatically be re-run when something in your database changes.
One solution is to wrap your query in shiny::reactivePoll(), which is actually used to implement shiny::reactiveFileReader()
For more information, see:
https://shiny.rstudio.com/reference/shiny/1.0.3/reactivePoll.html

Resources