-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4aa3b35
Showing
13 changed files
with
928 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# IDE / editor files | ||
*.iml | ||
.idea/ | ||
.idea_modules | ||
*.swp | ||
.vagrant | ||
|
||
# Ignore OSX stuff | ||
.DS_Store | ||
*/tags | ||
tags | ||
|
||
# Ignore generated stuff | ||
logs/ | ||
**/target/ | ||
.classpath | ||
.project | ||
.settings | ||
RUNNING_PID | ||
akka-diagnostics/ | ||
output/ | ||
*.orig | ||
|
||
# Deployment templates | ||
deploy/*/*.json | ||
conf/logback.xml | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
This software is licensed under the Apache 2 license, quoted below. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with | ||
the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. | ||
|
||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an | ||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific | ||
language governing permissions and limitations under the License. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
* PlantUml Rest Service API | ||
|
||
|
||
I created this tool trying to improve my local workflow as when I needed to | ||
render a new image I had to run =java -jar plantuml.jar= and JVM warm up is slow :( | ||
|
||
Also I use org-mode to render PlantUml directly on emacs, but calling an | ||
external java process it just destroys the workflow. | ||
|
||
I tried to use https://github.com/plantuml/plantuml-server but server is based on JEE and | ||
the protocol to call server needs some custom encoding. See [[http://plantuml.com/jquery_plantuml.js][js]] and [[https://github.com/dougn/python-plantuml/blob/master/plantuml.py][python]] remote clients. | ||
|
||
You can also use the server provided by PlantUml in http://www.plantuml.com/plantuml/png/, or | ||
might want to use all the available services online, but most of them are UI based and | ||
sometimes you don't want to paste your diagrams on public services. | ||
|
||
So, I just wrote a service that exposes an endpoint to create an image based on a | ||
plantuml string. | ||
I keep the service running on the background so there is no more JVM warming up involved. | ||
|
||
This service can be integrated with any decent tool/IDE as it's relaying on HTTP. | ||
|
||
** Tools used | ||
|
||
I think it's a good example of newcomers to Scala/Play as it's using routing, DI, custom dispatchers. | ||
And it has Unit Tests :p | ||
|
||
*** [[https://www.playframework.com/][Play Framework 2.5.4]] | ||
|
||
*** [[http://plantuml.com/][PlantUml]] | ||
|
||
|
||
** Example | ||
|
||
#+NAME: plantumltext | ||
#+BEGIN_EXAMPLE | ||
@startuml | ||
Diego -> World: hello | ||
@enduml | ||
#+END_EXAMPLE | ||
|
||
|
||
#+BEGIN_SRC sh :file /tmp/plantuml.png :var text=plantumltext :exports both | ||
echo "${text}" > /tmp/plantumltext.txt | ||
curl -s -X POST --data-binary @/tmp/plantumltext.txt -H "Content-Type:text/plain" localhost:9000/plantuml/png > /tmp/plantuml.png | ||
#+END_SRC | ||
|
||
#+RESULTS: | ||
[[file:/tmp/plantuml.png]] | ||
|
||
If you're using =curl= remember to use `--data-binary` instead of `-d` to preserve line breaks | ||
|
||
To know more about PlantUML, please visit http://plantuml.com/ | ||
|
||
** Creating a fat jar | ||
|
||
See https://www.playframework.com/documentation/2.5.x/Deploying#Using-the-dist-task | ||
|
||
** Using a precompiled jar | ||
|
||
Just go to [[https://github.com/d1egoaz/plantuml-rest-service/releases][Releases]]. | ||
Download the latest version. | ||
|
||
To run the application, unzip the file on the target server, and then run the script in the bin directory. | ||
Executable script comes in two versions, a bash shell script, and a windows .bat script. | ||
|
||
#+BEGIN_SRC sh | ||
$ unzip plantuml-rest-service-1.0-SNAPSHOT.zip | ||
$ plantuml-rest-service-1.0-SNAPSHOT/bin/plantuml-rest-service | ||
#+END_SRC | ||
#+BEGIN_EXAMPLE | ||
[info] play.api.Play - Application started (Prod) | ||
[info] p.c.s.NettyServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000 | ||
#+END_EXAMPLE | ||
|
||
** License | ||
|
||
This project uses PlantUML and that PlantUML is distributed under LGPL. | ||
|
||
** Roadmap/TODO: | ||
|
||
- Support additional image types. | ||
- json ??? | ||
- Rewrite plantuml dependency in go. | ||
|
||
Follow me on https://twitter.com/d1egoaz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import com.google.inject.AbstractModule | ||
import services.{PlantUml, PlantUmlCreator} | ||
|
||
class Module extends AbstractModule { | ||
override def configure(): Unit = { | ||
bind(classOf[PlantUml]).to(classOf[PlantUmlCreator]) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package controllers | ||
|
||
import play.api._ | ||
import play.api.mvc._ | ||
import scala.concurrent.ExecutionContext | ||
import services.PlantUml | ||
|
||
import javax.inject._ | ||
|
||
@Singleton | ||
class PlantUmlController @Inject() (plantuml: PlantUml)(implicit exec: ExecutionContext) extends Controller { | ||
|
||
def createImage: Action[String] = Action.async(parse.text) { request => | ||
val text = request.body | ||
Logger.debug(s"Converting to PNG\n$text") | ||
plantuml.createImage(text).map(bytes => Ok(bytes).as("image/png")) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package services | ||
|
||
import akka.actor.ActorSystem | ||
import net.sourceforge.plantuml.SourceStringReader | ||
|
||
import scala.concurrent.{ExecutionContext, blocking} | ||
import scala.concurrent.Future | ||
import java.io.ByteArrayOutputStream | ||
import java.io.IOException | ||
import javax.inject._ | ||
|
||
trait PlantUml { | ||
def createImage(text: String): Future[Array[Byte]] | ||
} | ||
|
||
@Singleton | ||
class PlantUmlCreator @Inject() (actorSystem: ActorSystem) extends PlantUml { | ||
|
||
private val myExecutionContext: ExecutionContext = actorSystem.dispatchers.lookup("contexts.plantuml") | ||
def createImage(text: String): Future[Array[Byte]] = { | ||
Future { | ||
blocking { | ||
val reader = new SourceStringReader(text, "UTF8") | ||
val baos = new ByteArrayOutputStream() | ||
val image = reader.generateImage(baos) | ||
try { | ||
baos.toByteArray() | ||
} finally { | ||
try { | ||
if (baos != null) { // scalastyle:ignore | ||
baos.close(); | ||
} | ||
} catch { | ||
case e: IOException => // ¯\_(ツ)_/¯ | ||
} | ||
} | ||
} | ||
}(myExecutionContext) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
name := """plantuml-rest-service""" | ||
|
||
version := "1.0-SNAPSHOT" | ||
|
||
lazy val root = (project in file(".")).enablePlugins(PlayScala) | ||
|
||
scalaVersion := "2.11.8" | ||
|
||
libraryDependencies ++= Seq( | ||
"net.sourceforge.plantuml" % "plantuml" % "8046", | ||
"org.scalatestplus.play" %% "scalatestplus-play" % "1.5.1" % Test | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
play.crypto.secret="@eMlaF6Pl]APrdDCUlUZ;gEJawkKOGGidw=nT5Eq_;nd]d@y5G4p7TLGSUEds1i[" | ||
|
||
contexts { | ||
plantuml { | ||
executor = "thread-pool-executor" | ||
throughput = 1 | ||
thread-pool-executor { | ||
fixed-pool-size = 10 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Routes | ||
# This file defines all application routes (Higher priority routes first) | ||
# ~~~~ | ||
|
||
POST /plantuml/png controllers.PlantUmlController.createImage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#Activator-generated Properties | ||
#Thu Aug 04 17:50:38 PDT 2016 | ||
template.uuid=f57599cf-a4f5-4333-9ff1-55d48fd49891 | ||
sbt.version=0.13.11 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// The Typesafe repository | ||
resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/maven-releases/" | ||
|
||
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.4") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import org.scalatestplus.play._ | ||
import play.api.test._ | ||
import play.api.test.Helpers._ | ||
|
||
class ApplicationSpec extends PlaySpec with OneAppPerTest { | ||
|
||
"Routes" should { | ||
|
||
"send 404 on a bad request" in { | ||
route(app, FakeRequest(GET, "/boum")).map(status(_)) mustBe Some(NOT_FOUND) | ||
} | ||
|
||
} | ||
|
||
"PlantUmlController" should { | ||
|
||
"creates a PNG image" in { | ||
var text = """ | ||
@startuml | ||
Bob -> Alice : hello | ||
@enduml | ||
""" | ||
val home = route(app, FakeRequest(POST, "/plantuml/png").withTextBody(text)).get | ||
|
||
status(home) mustBe OK | ||
contentType(home) mustBe Some("image/png") | ||
} | ||
|
||
} | ||
|
||
} |