I want to create a task defined by a macrodef within a script element. I was hoping to find that there would be 'set' functions corresponding to each attribute. No such luck. Is there some other API for specifying the attributes?
var statustask = project.createTask("service-status");
statustask.setPath(project.getProperty("path"));
statustask.setStatusproperty("status");
statustask.setTimeout=("1"); // this isn't suppose to take a long time.
statustask.perform();
You can probably achieve what you want using methods of the MacroInstance (a subclass of Task) you'll get from the createTask method for a macro. This:
<macrodef name="my.macro">
<attribute name="attr1" default="NOT SET"/>
<sequential>
<echo message="attr1=#{attr1}" />
</sequential>
</macrodef>
<script language="javascript"><![CDATA[
var macro = project.createTask( "my.macro" );
macro.setDynamicAttribute( "attr1", "value_1" );
macro.execute();
]]></script>
Produces this when run:
[echo] attr1=value_1
Related
I have a JSF composite component like this:
<cc:implementation>
<div id="#{cc.clientId}">
<h:outputScript library="js" name="helper.js"/>
<script type="text/javascript">
if(typeof variables === "undefined"){
var variables = {};
}
(function(){
variables.formid = '#{cc.clientId}';
})();
</script>
</div>
Value of variables.formid I'm using in a helper.js file. When I include this composite component only once, it's working like it should. When I include multiple composite components, every component receives the value of a last included composite component, how can I solve this issue?
There are basically 2 ways.
Add kind of "register" function to helper.js, so that you can explicitly register it there, instead of letting it to search for composites.
<h:outputScript name="js/helper.js" target="head" />
<div id="#{cc.clientId}">
...
</div>
<h:outputScript>helper.register("#{cc.clientId}", { foo: "somevalue" });</h:outputScript>
Options can be provided via a JS object as argument. This is also how a.o. PrimeFaces work with PrimeFaces.cw() function, whereby the "widget name" is also passed as an option.
Give the composite an unique style class like so:
<h:outputScript name="js/helper.js" target="head" />
<div id="#{cc.clientId}" class="your-foo-composite">
...
</div>
This way the helper.js can just collect them by class name during document ready.
// Vanilla JS:
var yourFooComposites = document.getElementsByClassName("your-foo-composite");
// Or if you happen to use jQuery:
var $yourFooComposites = $(".your-foo-composite");
Options can be provided as HTML5 data attributes (browser support is good these days).
<div id="#{cc.clientId}" class="your-foo-composite" data-foo="somevalue">
Which can be obtained as:
// Vanilla JS:
for (var i = 0; i < yourFooComposites.length; i++) {
var yourFooComposite = yourFooComposites[i];
var clientId = yourFooComposite.id;
var dataFoo = yourFooComposite.dataset.foo;
// ...
}
// Or if you happen to use jQuery:
$yourFooComposites.each(function(index, yourFooComposite) {
var $yourFooComposite = $(yourFooComposite);
var clientId = $yourFooComposite.attr("id");
var dataFoo = $yourFooComposite.data("foo");
// ...
});
It also keeps your HTML output free of inline scripts.
Unrelated to the concrete problem, usage of "js" as library name as in your initial code is not good. Carefully read What is the JSF resource library for and how should it be used? Also note that I added target="head" attribute to the <h:outputScript>. In case you're properly using JSF <h:head> component, it will let JSF autorelocate the script to the generated HTML <head> element.
I have a JSF composite component like this:
<cc:implementation>
<div id="#{cc.clientId}">
<h:outputScript library="js" name="helper.js"/>
<script type="text/javascript">
if(typeof variables === "undefined"){
var variables = {};
}
(function(){
variables.formid = '#{cc.clientId}';
})();
</script>
</div>
Value of variables.formid I'm using in a helper.js file. When I include this composite component only once, it's working like it should. When I include multiple composite components, every component receives the value of a last included composite component, how can I solve this issue?
There are basically 2 ways.
Add kind of "register" function to helper.js, so that you can explicitly register it there, instead of letting it to search for composites.
<h:outputScript name="js/helper.js" target="head" />
<div id="#{cc.clientId}">
...
</div>
<h:outputScript>helper.register("#{cc.clientId}", { foo: "somevalue" });</h:outputScript>
Options can be provided via a JS object as argument. This is also how a.o. PrimeFaces work with PrimeFaces.cw() function, whereby the "widget name" is also passed as an option.
Give the composite an unique style class like so:
<h:outputScript name="js/helper.js" target="head" />
<div id="#{cc.clientId}" class="your-foo-composite">
...
</div>
This way the helper.js can just collect them by class name during document ready.
// Vanilla JS:
var yourFooComposites = document.getElementsByClassName("your-foo-composite");
// Or if you happen to use jQuery:
var $yourFooComposites = $(".your-foo-composite");
Options can be provided as HTML5 data attributes (browser support is good these days).
<div id="#{cc.clientId}" class="your-foo-composite" data-foo="somevalue">
Which can be obtained as:
// Vanilla JS:
for (var i = 0; i < yourFooComposites.length; i++) {
var yourFooComposite = yourFooComposites[i];
var clientId = yourFooComposite.id;
var dataFoo = yourFooComposite.dataset.foo;
// ...
}
// Or if you happen to use jQuery:
$yourFooComposites.each(function(index, yourFooComposite) {
var $yourFooComposite = $(yourFooComposite);
var clientId = $yourFooComposite.attr("id");
var dataFoo = $yourFooComposite.data("foo");
// ...
});
It also keeps your HTML output free of inline scripts.
Unrelated to the concrete problem, usage of "js" as library name as in your initial code is not good. Carefully read What is the JSF resource library for and how should it be used? Also note that I added target="head" attribute to the <h:outputScript>. In case you're properly using JSF <h:head> component, it will let JSF autorelocate the script to the generated HTML <head> element.
Is there a way, inside the javascript code from WSO2 ESB's Script mediator, to get a property's value when this property has a scope different from "default" ?
In case of a property with default scope :
get-property('MyProperty')
OR
<script language="js">
mc.getProperty("MyProperty");
</script>
In case of a property with 'transport' scope :
get-property('transport','FILE_NAME')
OR
<script language="js">
mc.????????
</script>
It seems that you can not get properties of other scopes than synapse using
mc.get-property("Property Name")
since mc is instance of Synapse.MessageContext in order to get other message context properties I do something like this in java, I don't know that if it is applicable in javascript or not. I do this for axis2 message context properties.
Here "context" is the instance of Synapse.MessageContext.
org.apache.axis2.context.MessageContext axis2MessageContext;
axis2MessageContext = ((Axis2MessageContext)context).getAxis2MessageContext();
You can get property using this code:
<property name="ComingRoles" expression="your property or value" scope="default" />
<script language="js">var rolelist = mc.getProperty('ComingRoles');</script>
I test it with WSO2ESB 4.9.0
Update:
If your property is not define in default scope, first you must define it in default scope.
for example:
<property name="authheader" expression="get-property('transport','X-JWT-Assertion')"></property>
<script language="js"> var temp_auth = mc.getProperty('authheader')
</script>
It should works with ESB 4.5.0 and above
I don't think mc have get-property method.
Script Mediator use the Apache Bean Scripting Framework for scripting language support. And the mc variable represents an implementation of the MessageContext, named ScriptMessageContext.java.
[Here is the Class of ScriptMessageContext][1]
[1]: https://synapse.apache.org/apidocs/org/apache/synapse/mediators/bsf/ScriptMessageContext.html
You can check any DEFAULT scope property(method) in there.
If not, you may need to put these scope property in custom property.
Like:
<property name="CustomAction" expression="get-property('Action')"/>
Then use the getProperty("CustomAction") in JS to get them.
I did something like below
<property expression="json-eval($.)" name="JSONPayload"
scope="default" type="STRING"/>
<script language="js"><![CDATA[var pl_string = mc.getProperty("JSONPayload");
var newPayload="{\"event\": " + pl_string + "}";
mc.setPayloadJSON(newPayload);]]></script>
In my ANT scripts, I sometimes write tasks runnning javascript with Rhino.
However, I am at a loss as to how pass parameters into these tasks. Any ideas?
For example... here is an example of such a task:
<script language="javascript"> <![CDATA[
//some nonsense to fake out rhino into thinking we've a dom, etc.
this.document = { "fake":true };
this.window = new Object( );
this.head = new Object( );
eval(''+new String(org.apache.tools.ant.util.FileUtils.readFully(new java.io.FileReader('coolJavascript.js'))));
//... do some stuff
var s = java.io.File.separator;
var fstream = new java.io.FileWriter( ".." + s + "build" + s + "web" + s + "js" + s + "coolChangedJavascript.js" );
var out = new java.io.BufferedWriter( fstream );
out.write( jsCode );
out.close( );
]]> </script>
For using scripting to define an ant task you can use the scriptdef task instead of script. With scriptdef there are predefined objects to access the attributes and nested elements in your task.
This works for accessing attributes from javascript in Ant:
<scriptdef name="myFileCheck" language="javascript">
<attribute name="myAttribute" />
<![CDATA[
importClass(java.io.File);
importClass(java.io.FileReader);
importClass(java.io.BufferedReader);
var fileName = attributes.get("myAttribute"); //get attribute for scriptdef
var reader = new BufferedReader(new FileReader(new File(fileName)));
//... etc
project.setProperty("my.result", result));
]]>
</scriptdef>
Then can just go: <myFileCheck myAttribute="./some.file" /> same as you would for a regular ant task.
Also possible to use filesets etc if you want, more details at: http://ant.apache.org/manual/Tasks/scriptdef.html
The nice thing is you can define your tasks inline in your ant script, instead of writing them in Java then having to build and include the class files.
You will need to use Java1.6 (or later), or have apache BSF in your classpath.
Two suggestions come to mind. First, you can access Ant properties from within the javascript. There are examples in the documentation you refer to:
var x = project.getProperty( "my.property" );
can be used in the script to get the value of a property set in the XML, perhaps like this:
<property name="my.property" value="x" />
Second, you might consider using a scriptdef, which will allow you to define attributes and child elements that you can easily access from the javascript.
What I'm trying to do is compile to a file which takes it's version from a constant inside my source files.
I have a setup like this (or at least the significant bits):
tasks/compile.xml
<project name="Compile">
<target name="check.version">
<script language="javascript">
regex = /VERSION.+?"([\d\.]+)";/;
r = new java.io.BufferedReader(new java.io.FileReader(new java.io.File(file)));
line = r.readLine();
while ( (line = r.readLine()) != null) {
m = regex.exec(line);
if (m) {
project.setProperty( "project.version" , m[1] );
break;
}
}
r.close();
</script>
<echo>${ant.project.name}-${project.version}</echo> <!-- = Fail-0.2 -->
</target>
</project>
And a build.xml:
<project name="Fail">
<import file="${basedir}/build/tasks/compile.xml"/>
<target name="test">
<antcall target="check.version">
<param name="file" value="${basedir}/Source.as"/>
</antcall>
<echo>${project.version}</echo> <!-- = ${project.version} -->
<echoproperties></echoproperties>
</target>
</project>
So, it seems that the property set by the script is only locally defined in that target, if i specify another target in the same project ("Compile") it won't know of that property either.
I've also tried to set a in the "Compile"-project xml but it won't be overwritten by the target anyway.
So how can I access that property generated by the script? Or is there another way for doing something like this?
I'd really like to keep that part in a separate xml as it makes the project build script so much cleaner.
Thanks!
If you call the other target via antcall, properties set within it won't be in the scope of the caller.
If you need to access properties set by another target, you could declare that target as a dependency to ensure that it gets executed before your target. Like this:
<target name="test" depends="check.version">
<echo>${project.version}</echo> <!-- = value set in check.version -->
<echoproperties></echoproperties>
</target>
Edit: There's also the AntCallBack task which is available from Ant-Contrib and Antelope:
AntCallBack is identical to the
standard 'antcall' task, except that
it allows properties set in the called
target to be available in the calling
target.