Where do I put my resources in Scala? - scala

While studying using Scala with JavaFX I have met the following code in a ProScalaFX example:
val resource = getClass.getResource("AdoptionForm.fxml")
if (resource == null) {
throw new IOException("Cannot load resource: AdoptionForm.fxml")
}
...
val root: jfxs.Parent = jfxf.FXMLLoader.load(resource)
Where do I put the actual "AdoptionForm.fxml" content in this case? Unfortunately I am neither familiar with using resources in Java.
I use SBT as the building system and Idea as an IDE.
There is a related question which suggests a way (putting the resource files in "src/main/resources" or "src/main/resources/packagename"), but it also says it doesn't work actually (needless to say I have tried).

src/main/resources is the correct location for placing resources in a default SBT configuration.
However, one has to be aware of the difference between getClass.getResource and ClassLoader.getResource. Using getClass.getResource("AdoptionForm.fxml") requires the file to be located in a path which corresponds to the package of the class.
For instance: If the class is located in com.domain.utils then the resource must be located at src/main/resources/com/domain/utils/AdoptionForm.fxml.
In order to switch from package-relative locations to absolute locations one can either use ClassLoader.getResource or just prepend the resource string with a /.
Example: getClass.getResource("/AdoptionForm.fxml") loads the resource from src/main/resources/AdoptionForm.fxml

Related

Adding resource to project-specific SBT autoplugins

SBT lets you define autoplugins specific to your project by putting them in ./project.
I'm trying to add resources to one such autoplugin - by which I mean something that it could access through a call to getClass.getResourceAsStream.
I have, however, not been able to work out how to do that, or even if it was possible. There's no documentation that I could find on the subject, and the obvious (simply putting resources in ./project with the plugin) fails.
Is what I'm trying to achieve possible?
Yes, you need to place your resource in ./project/src/main/resources/
For a quick demonstration that this works, assume the file name is test.txt, put the following in your build.sbt:
lazy val hello = taskKey[Unit]("prints the content of test.txt")
hello := println(IO.readStream(getClass.getResourceAsStream("test.txt")))

Play Framework 2.2.x: Static assets location not working in production

Having trouble accessing the compiled assets location in production.
My strategy has been to serve my assets in "app/assets/ui" when in development and "public" when in production this is done as shown below in my conf/routes file
#{if(play.Play.mode.isDev())}
GET /assets/*file controllers.common.Assets.at(path="/app/assets/ui", file)
#{/}
#{else}
GET /assets/*file controllers.common.Assets.at(path="/public", file)
#{/}
Since i have defined asset mappings outside “public,”I have added the following line in my Build.scala
playAssetsDirectories <+= baseDirectory / "app/assets/ui"
As an example my scripts are loaded conditionaly depending on the environment as shown below
#if(play.Play.isDev()) {<script src="#routes.Assets.at("/app/assets/ui", "javascripts/application.js")"type="text/javascript"></script>} else {<script src="#.routes.Assets.at("/public", "javascripts/application.min.js")" type="text/javascript"></script>}
I'm using Grunt for my frontend workflow and when the application builds it copies the distribution files to the application's public folder.
I start the app in production using "sbt clean compile stage" and then run the packaged app.
My problem appears that the routes are still referring to the "app/assets/ui" folder instead of the distribution "public" folder.
Any tips on how i can debug this? My working background is as a front end developer so i'm very new to Play! and scala.
As mentioned by #estmatic, your conditional in routes won't be evaluated.
As it's generally extremely useful to consolidate the differences between application Modes into files, I'd suggest you extend GlobalSettings (if you aren't already) and override the onLoadConfig method:
class Settings extends GlobalSettings {
override def onLoadConfig(config: Configuration, path: File, classloader: ClassLoader, mode: Mode.Mode): Configuration = {
val specificConfig:Config = // ... Use the mode param to load appropriate file
super.onLoadConfig(specificConfig, path, classloader, mode)
}
...
}
You could then have appropriately-named files (dev.conf and production.conf spring to mind) that contain suitable values, one of them being the base path for the Assets controller to use.
EDIT turns out doing it this way makes usage in routes awkward, here's another approach:
This approach does not use a configuration file per-environment, which means that if something changes in the frontend configuration (e.g. it's no longer served up from /public) you'll have to change this code and re-deploy it. However, it fits into Play 2.x pretty nicely:
package controllers
object EnvironmentSpecificAssets extends AssetsBuilder {
val modeToAssetsPathMap = Map(
Mode.Dev -> "/app/assets/ui",
Mode.Prod -> "/public")
lazy val modePath = modeToAssetsPathMap(Play.current.mode)
/** New single-argument `at`, determines its path from the current app mode */
def at(file:String): Action[AnyContent] = at(modePath, file)
}
The code is pretty self-explanatory, the only "trick" is probably the lazy val which means we only have to evaluate the current operating mode and do the map lookup once.
Now your routes file just looks like this:
GET /assets/*file controllers.EnvironmentSpecificAssets.at(file)
Playframework 2.x doesn't support conditional statements in the routes file. The 1.x versions had this but it was removed.
What you have in your routes file is simply two routes with the same URI pattern, /assets/file*. The other lines are just being ignored as comments since they begin with the pound character, #. I think since the pattern is the same for both the first route is catching everything and the second isn't doing anything.
It's not exactly what you're trying to do but I think you can just make the route patterns a bit different and it should work.
GET /assets/dev/*file controllers.common.Assets.at(path="/app/assets/ui", file)
GET /assets/*file controllers.common.Assets.at(path="/public", file)

How to determine absolute file path of a Java source file in Eclipse plugin?

In my custom Eclipse plugin, I have the fully qualified class name of a Java class as a String, and want to know its actual file path. In fact, I want to know the name of the source folder it resides in.
The class could be from any of the Java projects in the Workspace. The source folder names are arbitrary.
I use Eclipse 3.6.
Thanks!
You will have to use the search engine API. See org.eclipse.jdt.core.search.SearchEngine.
You can see that there are various static functions you can call, each with their own options. You will need to create an appropriate org.eclipse.jdt.core.search.SearchPattern and then pass it to the search engine along with a scope (the workspace) and a requestor (something that gathers all of the results).
Typically, you will get a bunch of stuff back, like ITypes, which are the public API for accessing types in the Java model. You can call IType.getResource().getLocation() to get the filesystem location of any type. The getResource method may return null, so you need to check for that.
You will need to use the JDT API stuff to get to the IResource of the Java class. From there you can use the Resource API to get the containing folders and whatever else you need.

How to use Ostrich

I have a task to collect and report some runtime statistics for my application. Ostrich looks quite friendly in both API and feature set. But I can't find any documentation about the most of declared features. Especially it is difficult to configure stats reporting through the web interface without any understanding of configuration principles.
So my main question: is there any documentation besides the README?
If no, could someone give an example of the following features (all of them are from the top of README):
load & reload per-environment configuration (there is example on SO already, but what if I want to use a classpath resource? how to define an environment? how to reload configuration?)
report statistics into log files
Or (perfectly) give a good architectural overview of configuration in Ostrich so I can find some way to do configuration by myself.
Ostrich config files are just regular scala classes, so if you want to load a classpath resource, you probably should create the config instance in code instead.
Here is how I load default config if -f command-line arg is not specified:
val runtime = RuntimeEnvironment(this, args)
val server =
if (runtime.configFile.exists) {
runtime.loadRuntimeConfig[Server]()
} else {
(new RPCServerConfig)()(runtime)
}
Note that you have to
- create config instance
- then call it's apply() method
- then apply(runtime) on the result
You can easily extend this to load different configs depending by e.g. lift's Props.mode

Error with Groovy AST transformations when cleaning project in Eclipse

I'm trying to work through groovy's Implementing Local AST Transformations tutorial, but whenever I clean my project I get this error in each file that has the #WithLogging annotation in it:
Groovy:Could not find class for Transformation Processor AC.LoggingASTTransformation declared by AC.WithLogging
So you have a package named "AC" that contains both "WithLogging.groovy" and "LoggingASTTransformation.groovy" classes? Does it also contain any classes that implement the "WithLogging" interface?
If so, I'd suggest you move the class(es) that use your annotation to a location outside of the annotation defining package (the default will suffice, for diagnostic purposes) - Order of compilation matters with transformations. See this post on the groovy users mailing list for more on that.
Also try changing the annotation from #WithLogging to #AC.WithLogging.
As far as cleaning with Eclipse is concerned, I had a similar issue and found that I had to make a trivial modification after a clean to any file that contained my annotation. IE, add a space somewhere. Then save the file. This should rebuild everything properly.