Dynamic templates in Play Framework 2.0 - java

There is TemplateLoader in Play 1.0 for generating templates in runtime.
Is there any solution to dynamically load template in Play 2.0? Or can I somehow convert it to scala code for using Eval?
For example: I want to store some templates in the database, so that certain users could edit them.

Play 2.0 already compiles your templates to object methods, so you don't have to 'dynamically load' them!
Consider this simple template called app/views/test.scala.html.
#(num:Long)
Your number is #num
It becomes a Scala method of views.html called test. Evaluate it with this code:
val msg : String = views.html.test(23).toString()
You don't have to use html views only. To use templates with strings, use the play.api.templates.Txt derived classes. This is a template called app/views/quick.scala.txt:
#(id:Long)Your id is #id
It becomes a method views.txt.quick and is used:
val msg2 : String = views.txt.quick(32).body
You can find out more in the documentation for the the play.api.templates package.

It seems the relevant code is in framework/src/play/src/main/scala/system/ApplicationProvider.scala in the Play-2.0 directory, particularly the ReloadableApplication class. I'm unsure how this compiling on the fly would suit you, since you don't want to do it when the template is requested (it is slow). Which means that storing in a database doesn't quite make sense: you don't want to store the template source code, but rather the compiled template object.
For arguments sake, if you just wrote the templates to the app/views directory, you could leave Play to compile them at its leisure. But then, beware, because they probably won't compile on a production system.

Related

How can I get PMD result report as java object from code?

I'm writing something like PMD wrapper (the goal is to check the java code with PMD, but with certain features), pmd-core and pmd-java included to my project like external libraries and I'm executing PMD such way:
int violations = PMD.doPMD(configuration);
doPMD returns number of violations found. By configuring reportFormat in PMDConfiguration we can set output to System.out or to file with one of the available report formats (like xml, html, text, etc.), but...
How can I get PMD result (of all source files were processed) report as java object? Perhaps, it is possible to get a list<> of all RuleViolations or something else.
You can use a custom Renderer.
Create a custom implementation of net.sourceforge.pmd.renderers.Renderer
On your configuration call setReportFormat passing the fully quallified name of your custom renderer (ie: "my.organization.package.InMemoryRenderer")
run the analysis, just as you are doing
During the analysis process, your renderer will be instantiated exactly once, and renderFileReport(Report) method will be called for each file's results. The Report has method's to obtain and iterate over violations, config and execution errors.
These are provided as POJOs, as you intend.
You won't have access to the Renderer instance, but you can store data in a static member (make sure to keep thread-safety as PMD runs multithreaded analysis!) and provide a static getter.

Can GWT optimize raw javascript along with its generated output?

For a couple of reasons, I'm interested in writing a hybrid application which is partially coded in Java (via Google Web Toolkit) and partially coded in JavaScript. I'm planning on calling the Java library from JavaScript by using GWT Exporter.
The trouble is that this destroys a lot of the opportunities for code optimization and compression. GWT is mostly just designed to optimize the JavaScript it generates, and third-party Javascript compression libraries will probably break down when given GWT output.
Is there a way to tell the GWT compiler "hey, pass these Javascript files into your optimization pass as well"? GWT has a flag for using the Closure Compiler under the hood (which obviously supports optimizing regular javascript), so it feels like this should be possible.
Insofar as you can ask Closure to compile source, it is possible, but you have to get those 'other' sources into the code that GWT (and later closure) is compiling. Presently, this means putting that code in JSNI, otherwise it is just another file on the filesystem, and the compiler can't know what the dependencies in and out are, since it likewise can't tell when/how you are loading that file.
If I remember correctly, standard usage of dependencies in Closure is via a goog.require() method call in JavaScript at the top of your file - this both declares the dependency, and if needed loads the file. Without this, your base HTML page needs to have <script> tags for each file you might possibly use, and without actually running that page, Closure won't know what order to expect those files to load in, or how far and wide to run when compiling your source.
GWT itself (i.e. outside of Closure) only makes a very small set of optimizations to the raw JS included as JSNI in its Java sources:
com.google.gwt.dev.js.JsStaticEval - simple constant folding, and other expression simplification
com.google.gwt.dev.js.JsInliner - inline functions under a certain complexity threshold, and other assorted cleanup
com.google.gwt.dev.js.JsUnusedFunctionRemover - simple pruning of unreferenced functions/variables
com.google.gwt.dev.js.JsDuplicateCaseFolder - look for the same body in more than one case block and merge them into one fall-through case.
GWT has three primary ways to include JS source: JSNI, tags in the .gwt.xml (not supported by all linkers) and com.google.gwt.core.client.ScriptInjector to pull from a string constant or from a remote url. Only the first considers the code as actual source - the second/third let the code come from any source, and don't count on the code being statically available at compile-time. JSNI has its own limitations - it doesn't support with blocks, and must use $wnd and $doc to refer to the host page's window and document.
First, although this is not your question, you have to be aware that to use gwt-exporter you have to call GWT.create per each class you want to populate, or call the exportAll() method for exporting everything marked as exportable. That implies that you are saying to the compiler that you are going to use those classes even your JS app would eventually not use them. So you wont take advantage of the removal of unused code causing large js output. You could use code-splitting for separate code in fragments though.
Second, and related with your question, as #Colin says in his answer only code written in JSNI blocks will be optimised by the GWT compiler, but the default optimisation is very trivial, although if you use the closure compiler it is a bit stronger. I have not tried, but I think closure annotations are not allowed since probably GWT compiler removes them before passing the js to the closure compiler.
Anyway, the main problem for including those files in JSNI blocks, is that you have to copy and paste the code in your java classes manually, and then perform some other tricks for addressing $wnd, etc.
We at gwt-query have a JsniBundle generator able to take .jsfiles from filesystem or from any url, and in compile time include that code in JSNI fragments and make a couple of tricks to make it work in the iframe where GWT runs. It works for almost libraries and plugins I have used, but sometimes I had to modify the javascript source for allowing sand-boxing it.
Here you have an example of how to include jquery and highcharts:
public interface JQueryBundle extends JsniBundle {
#LibrarySource(value =
"http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js")
public void initJQuery();
}
public static abstract class HighCharts implements JsniBundle {
#LibrarySource("js/highcharts.src.js")
public abstract void initHighcharts();
public void drawChart(String id, JavaScriptObject props) {
JavaScriptObject $container = JsUtils.runJavascriptFunction(window, "$", "#" + id);
JsUtils.runJavascriptFunction($container, "highcharts", props);
}
}
public void testHighCharts() {
JQueryBundle jQuery = GWT.create(JQueryBundle.class);
HighCharts highCharts = GWT.create(HighCharts.class);
jQuery.initJQuery();
highCharts.initHighcharts();
highCharts.drawChart("chart", charData);
}
Some of the advantages of using this method are enumerated in this slide of our GWT.create-2013 presentation.
You can optimize arbitrary JavaScript code using the GWT compiler, just use the appropriately named LinkerContext.optimizeJavaScript(TreeLogger, String) method. LinkerContext objects are available inside Linkers, which are pieces of custom code run during the compilation. Here's a minimal example on how to write one:
#LinkerOrder(LinkerOrder.Order.POST)
public class ScriptOptimizer extends AbstractLinker {
#Override
public String getDescription() {
return "Optimizes external JavaScript files.";
}
#Override
public ArtifactSet link(TreeLogger logger, LinkerContext context,
ArtifactSet artifacts) throws UnableToCompleteException {
// This is some arbitrary JavaScript code you'd probably want to read
// from a static file in your classpath
String script = "var foobar = 1; for (var i = foobar; i < 5; i++) alert(1);";
// Do the optimizations
script = context.optimizeJavaScript(logger, script);
// Create an Artifact from the optimized JavaScript string
ArtifactSet newArtifacts = new ArtifactSet(artifacts);
newArtifacts.add(emitString(logger, script, "example.js"));
return newArtifacts;
}
}
Then, to include the Linker in your GWT compilation process, add this to your *.gwt.xml:
<define-linker name="scriptoptimizer"
class="com.example.ScriptOptimizer" />
<add-linker name="scriptoptimizer" />
The result will be a compiled file called example.js. You can of course generate as many files as you want or, for optimal results, concatenate all your scripts into one and compile that into a single output file.

Is there a way to add a custom class template to Eclipse?

Here's the scenario. I often create classes that follow a certain pattern. All classes extend a base abstract class (out of my control) with certain methods I wish to always override, including the constructor. I'd like to rightclick on my package name, click New, and then click "Foo Class". I'd then have a class added to my project, but using the "Foo" template instead of the standard class template. I understand I can change the class template, but I don't want to change it for all classes. Is this possible without writing a full blown extension?
you can use the editor template to create a new template and use that.
Go to Preferences->Java->Editor->Templates and create your template there.
Then create a new class file and apply your template.
Unfortunately no. What you'd like to achieve needs writing an eclipse plugin.
I'd suggest setting up a Template (at Preferences | Java | Editor | Templates) and giving it a short useful name describing your scenario. Whenever you'd want to write an additional template class, you could create a new class, press Ctrl+A, Del (select all and remove), then type "name Ctrl+Space" and have your template there as configured.
ps. I'd really review your requirement, can't think of a valid approach at the moment which would require writing many similar classes without a valid way to remove the code duplication you are just about to introduce.

Invoking acceleo template from java app

Hi all i'm very new to acceleo
In my project, i have a java driver class which calls different acceleo templates. Some of the templates have parameters without any EObject type. I am calling calling initialize() and doGenerate() functions of generated java module for a template. the problems are facing are :
initialize() expects the first argument to be Ecore object and rest of parameters are as List. However as I mentioned some of the templates do not have any EObject parameters. How do I call such templates from a java application?
To work around the above problem, i adjusted my driver and templates to have dummy EObject as first parameter. Then it calls templates successfully but it won't generate any output. The templates generate output if I call them from another driver template though. However I do not want to write my driver program in MTL as it requires complex analysis of data model.
Please advice me on how can I progress in my case.
Thanks&Regards
Dhanunjaya M.
The API we expose by default through the Java class we generate alongside the "main" templates' modules and the Acceleo "facade" classes always assume that there is an EObject as first parameter of the templates that are to be called. This has been made in order to facilitate the use for most use cases (we expect this use case to be 90% of the total).
For other use cases, you will have to make use of the APIs that are behind those facades. Namely, you can create another "initialize" method that does not take an EObject as parameter for these cases when you simply don't have one. You will then need to also override the "generate(Monitor)" method so that it does not use AcceleoService.doGenerate... or any other method of AcceleoService for that matter : this is the "facade" class that I was talking about.
What you will need is to call a method that mimics what AcceleoService.doGenerate does without relying on an EObject to find the template that needs to be called. If you do not have Acceleo's SDK or sources at hand, you can take a peek at the code through github : AcceleoService#doGenerate.

Can Java self-modify via user input?

I'm interested in an executed script allowing user input to modify the process and corresponding source.
What precedents exist to implement such a structure?
Yes, depending on what is meant.
Consider such projects as ObjectWeb ASM (see the the ASM 2.0 tutorial for a general rundown).
Trying to emit the-would-need-to-be-decompiled Java source code is another story: if this was the goal then perhaps the source should be edited, re-compiled, and somehow loaded in/over. (This is possible as well, consider tools like JRebel.)
Happy coding.
You should not be able to modify existing classes. But if you implement a ClassLoader then you can dynamically load classes from non-traditional sources: network, XML file, user input, random number generator, etc.
There are probably other, better ways.
Maybe the Java scripting API is what you're looking for:
http://docs.oracle.com/javase/6/docs/api/javax/script/package-summary.html
http://docs.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html
I wrote an app once that used reflection to allow tests to be driven by a text file. For instance, if you had a class like this:
class Tuner(String Channel) {
tune(){...
play(){...
stop(){...
}
You could execute methods via code like:
tuner=Channel 1
tune tuner
play tuner
stop tuner
It had some more capabilities (You could pass objects into other objects, etc), but mostly I used it to drive tests on a cable box where a full write/build/deploy in order to test took on the order of a half hour.
You could create a few reusable classes and tie them together with this test language to make some very complex and easy to create tests.
THAT is a DSL, not monkeying around with your loose-syntax language by eliminating parenthesis and adding underscores and dots in random locations to make it look like some strange semi-English.

Categories

Resources