Bharadwaj
Bharadwaj

Reputation: 1351

Reading files from directory in Play framework on Heroku

I have a directory with deep structure (lot of sub-directories and files) that I read from my play application. On my PC I read the directory using -

val directory = Play.getFile("directory")
for(file <- directory.listFiles) {
  val lines = Source.fromFile(file).getLines()
}

This works perfectly on my PC but not on Heroku. On Heroku I get a NPE on line#2 (above code) which means that the directory object is not getting made.

This suggestion of a similar issue suggests that I could put my directory in public and read it as using the Play.resource API. But I DONT want to put my directory in public. And I have a need to list the contents of a directory as it could be changing... how can I do this in Play on Heroku?

Upvotes: 1

Views: 2222

Answers (3)

Supun Wijerathne
Supun Wijerathne

Reputation: 12958

As this suggests,in order to make Play.getFile("location_from_project_root") (or any other similar one) working in production environment, you have to explicitly ask from play to add the directory where you put the file ,to the dist.

Ex:

You want to access a file Project_Root/resources/mtFile.json, (inside /resources folder you created), you can use Play.getFile("/resources/mtFile.json")method.

But in order to make it works in any production environment, you have to add /resources folder to the dist. Otherwise that file will not be there. In order to do that you have to add these lines into your build.sbt file.

import com.typesafe.sbt.packager.MappingsHelper._
mappings in Universal ++= directory(baseDirectory.value / "resources")

Now, if you take a dist using activator dist command you can see that a directory called /resources has added into the root of the dist. Now Play.getFile("/resources/mtFile.json") should work in production environment.

Upvotes: 1

ndeverge
ndeverge

Reputation: 21564

You can put your files under your conf folder, so that the files are not publicly available. Then use :

Play.resource("conf/directory"): Option[URL]

or

Play.resourceAsStream("conf/directory"): Option[InputStream]

Upvotes: 0

Sudheer Aedama
Sudheer Aedama

Reputation: 2144

Play.getFile(relativePath) retrieves a file relative to the current app's root path. Current app's root path may not be same on your PC and Heroku.

One more thing: Your statement that the directory object is not getting made is not true. listFiles operation is throwing NPE in your case.

Try this to get a list of files from your directory:

 val listOfFilesInDirectory: List[java.io.File] = Option(getClass.getResource("/directory")).map(_.toURI).map(new java.io.File(_)).map(_.listFiles).flatten.toList

Upvotes: 0

Related Questions