How to access PlayRunHooks trait and PlayKeys from inside a sbt plugin - scala

I want to include the workflow of the Ember CLI into a Play! application. I decided to write an sbt plugin that, when enabled in the play applications build, will do a few things:
Add a task to run "ember new" to create the UI project in a sub directory.
Add a PlayRunHook so that when run is executed from the activator shell, it also starts the node server serving the EmberJS application by setting the proper proxy such that the api calls are proxied to the Play! application.
When the package is called, it also packages the EmberJS application.
Properly sets up the UI Assets to include the EmberJS application.
The problem is I am not able to find out how to add a dependency so that I can use the PlayRunHook trait and PlayKeys in my sbt plugin.
I want to use the plugin route because in the future I may have more services that will have the same kind of workflow.
Update:
I could not find out a way to create this plugin as I was not able to access PlayRunHook from that plugin. But, I have implemented what I wanted as a seed project. Link: https://github.com/dipayanb/play-ember-seed
While writing the sbt plugin I was not able to write a class similar to https://github.com/dipayanb/play-ember-seed/blob/master/project/EmberRunner.scala as I was not able to compile the code from inside the plugin.

Without seeing the code you're using to try and implement the plugin, this will be hard to answer, but in short you need to add the Play! plugin to your plugin's build definition. That is added in the same way as usual, inside your plugin's project/plugins.sbt:
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % playVersion)
Because SBT is recursive, it is not sufficient that your project has the plugin you're trying to access: your plugin needs to load the plugin itself.

Related

Artifactory plugin calling another plugin

Is there a way to call another artifactory plugin from an artifactory plugin?
We use artifactory user plugins a lot in our company and it works fine but sometime we could see the need to call directly another plugin instead of copying the code around...
If your goal is reusing logic between plugins, you can encapsulate this logic in Java classes and import them in your plugins. You can package the reusable code in a java archive (jar) and place it as a library under the ${ARTIFACTORY_HOME}/etc/plugins/lib directory.

Publishing / Resolving Custom SBT Plugins with Nexus

I've created my first SBT (1.x) AutoPlugin to add some settings and behavior to projects that use the plugin.
When I publish it locally, everything resolves and works correctly for the projects using the plugin.
However, when I publish the plugin to our private Nexus repository, it fails to resolve for any projects attempting to use it.
I realize that when sbt plugins are published locally, the path is different than 'regular' sbt projects, but they still resolve correctly for projects which use them.
Do I need to publish sbt plugins to a different location within Nexus than our other Scala / SBT-based projects?
And / or, do I need to set up a new resolver for Nexus-hosted SBT plugins?
I know similar questions have been asked previously, but being new to both Nexus and plugin creation, I haven't been able to figure out exactly what I need to do to get the plugin to resolve correctly when publishing to Nexus rather than simply doing a publishLocal and then adding it to the plugins.sbt file of projects meant to use the plugin.
Any assistance would be very much appreciated!

Play Framework Project: How to include plugin from source

Background:
I am in the process of integrating TypeScript into a Play Framework (2.2.6) and I am trying to use mumoshu's plugin to do so. Problem is, the plugin has problems when running "play dist" on a windows machine.
I've forked the code from GitHub in order to make some modifications to the source so I can continue using the plugin.
Question:
I have a play framework plugin in the traditional source structure:
project/build.properties
project/Build.scala
project/plugins.sbt
src/main/scala/TypeScriptPlugin
src/main/scala/TypeScriptKeys.scala
...<other code>
I'd like to include this plugin into another project but I don't really know where to start and how to hookup the settings.
From previous suggestions, I've been able to add the module to my project as follows:
// In project/Build.scala...
object ApplicationBuild extends Build{
lazy val typeScriptModule = ProjectRef(file("../../../play2-typescript"), "play2-typescript")
lazy val main = play.Project(<appName>, <appVersion>, <appDependencies>).settings(typescriptSettings: _*).dependsOn(typeScriptModule).aggregate(typeScriptModule)
}
Where typescriptSettings is defined in the other project... I think, I'm still not 100% sure what typescriptSettings IS other than adding this settings call enabled the plugin to work. This worked fine originally when I had included the plugin in the plugins.sbt file and imported the package com.github.mumoshu.play2.typescript.TypeScriptPlugin._ but now that I'm including the source and explicitly including the module, I can't just import the package... Or at least not the way I used to.
I am still new to scala/sbt and I am having difficulty finding helpful resources online. Any help would be appreciated.
Assuming in the same parent directory you have two directories:
play2-typescript: which is a clone of mumoshu's play2-typescript
play2-typescript-testapp: which is the play app in which you're testing your changes
You need to create, inside play2-typescript-testapp's project directory a file like so:
play2-typescript.sbt
val metaBuild = (project in file(".")
dependsOn ProjectRef(file("../../play2-typescript"), "play2-typescript")
)
Note:
The relative path is to the play2-typescript plugin project, and is relative to the project directory inside play2-typescript-testapp.
Change that to what is correct in your setup, and consider that you can also define it as an absolute path.
There a lots of activator template examples of this. I have a project where we followed the https://typesafe.com/activator/template/play-multidomain-auth path. Specifically, to address your question; the plugins in the root project play-multidomain-auth/project/ are accessible in the modules (play-multidomain-auth/modules/admin/, .../common, and .../web).
This example is the cleanest example I've seen in using multi-project design however that opinion is very subjective.
I hope this helps.

How to resolve classpath incompatibilities between plugin code and IntelliJ SDK

I am currently trying to develop a plugin for IntelliJ that will use a "core" library. The core library already has it's own dependencies (JAR files) and is used in other non-IntelliJ projects. Unfortunately some of the dependencies of the IntelliJ SDK are the same as that for the plugin core, but with conflicting versions. So far this has been manageable because we remove the dependencies in the SDK and provide the core's dependencies instead, and running the plugin through IntelliJ to work fine. However, I really want to be able to write automated unit tests for the plugin, and this causes problems.
Following the instructions from here, I set my first unit test to extend LightCodeInsightFixtureTestCase. However, this fails to get past the setUp method, throwing NoClassDefFoundErrors. See the gist of the error here (picocontainer is the conflicting dependency).
By inspecting the classes loaded while running the plugin, I can see that the same class from a conflicting dependency is loaded in two different classloaders, a URLClassLoader for the com.intellij dependency, a PluginClassLoader for my plugin's dependency. This explains why the plugin can be executed successfully, but the test fails.
A small, self contained example of a project that fails in this way is available here: https://github.com/holger-s/libraryconflict
My question is, what is the recommended way to resolve these conflicts that allows unit testing with the IntelliJ test fixtures?
Full disclosure: I have also sought an answer on the IntelliJ Plugin Development forum.
So this is late, but was running into the same problem, and I fixed it by adding the library under Project Structure/Libraries, then going to Modules/Dependencies, and changing the scope to Provided.
https://confluence.jetbrains.com/display/PhpStorm/Setting-up+environment+for+PhpStorm+plugin+development

SecureSocial not using extended classes in Play! 2.1 project inside SBT Multi-Project

Currently I have a Play! 2.1 project that is a sub-project of an SBT Multi-Project that is a front-end interface. The Play! project uses SecureSocial for typical authentication.
I will typically first start the SBT console to run my internal services locally in separate terminals. Finally I perform a play "project interface" "~run 9000" command in a new window to start up the interface sub-project using Play!. Problem is that on a fresh load (even after a clean) SecureSocial does not use my extended services and providers, and instead falls back on its own.
I will make a source change and reload, where SecureSocial will then use my own classes but suddenly starts throwing ClassCast exceptions using two of the same types, indicating there are conflicting ClassLoaders.
Is there a proper way to set this up so this doesn't happen? Thanks for your help!
Though not a real solution, I have in the meantime developed a workaround where I manually instantiate my own extended UserService class and bring the current Application instance into scope. I also wrote my own providers and SecureAction wrappers and designed them to use the custom UserService. It's a lot of extra code, but works around the problem.