How to point centralized location for multiple workflows in oozie - java

I have more than 10 oozie workflows. Each workflow.xml, coordinator.properties and xml plus lib folder is in a separate folder. All the workflow have some common jars around 6mb size and I have to copy same jar in each lib folder. Can you please tell me the best possible solution to have a common jar location, so that i don't need to copy same jar in each workflow folder for java actions.
<action name="aggr_stage" retry-max="3" retry-interval="1">
<java>
<main-class>com.*.*.ReportGenerator</main-class>
<arg>${reprocessing}</arg>
<arg>${timeZone}</arg>
</java>
<ok to="notifyJobSuccess" />
<error to="notifyJobFailure" />
</action>

Add a <file> tag in your oozie action. Refer same file for each and every action.
see oozie docs
<action name="aggr_stage" retry-max="3" retry-interval="1">
<java>
<main-class>com.*.*.ReportGenerator</main-class>
<arg>${reprocessing}</arg>
<arg>${timeZone}</arg>
<file>hdfs://<namenode>:<port>/<path-to-your-jar>/your-report-generator.jar</file>
</java>
<ok to="notifyJobSuccess" />
<error to="notifyJobFailure" />
</action>
Instead of using full hdfs path you can also use relative path to that jar from your workflow.xml in your file tag to add the file.
example: ../../your-report-generator.jar

Related

Oozie Java Action Error java.lang.NoClassDefFoundError: org/apache/poi/xwpf/usermodel/XWPFDocument

I am trying to run a oozie workflow for java action. My Java code can read a Word file from HDFS and write backs CSV files on HDFS.
My workflow.xml contains -
<?xml version="1.0" encoding="UTF-8"?>
<workflow-app xmlns="uri:oozie:workflow:0.4" name="Word-Processing">
<start to="PathologyReport-Processing"/>
<action name="PathologyReport-Processing">
<java>
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
<property>
<name>oozie.libpath</name>
<value>${JarPath}</value>
</property>
</configuration>
<main-class>${MainClass}</main-class>
<arg>-libjars</arg>
<arg>${JarPath}</arg>
<arg>${in}</arg>
<arg>${out}</arg>
</java>
<ok to="end"/>
<error to="fail"/>
</action>
<kill name="fail">
<message>Java Action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
</kill>
<end name="end"/>
</workflow-app>
My job.properties contains following code
nameNode=hdfs://CTSC00385700501:8020
jobTracker=CTSC00385700501:8032
workflowRoot=PathologyReport
queueName=default
MainClass=SampleUnstructured
JarPath=hdfs://localhost:8020/user/oozie/${workflowRoot}/lib/poi-3.9.jar
in=hdfs://localhost:8020/user/oozie/${workflowRoot}/SampleWord.docx
out=hdfs://localhost:8020/user/oozie/${workflowRoot}/output
oozie.use.system.libpath=true
oozie.libpath=hdfs://localhost:8020/user/oozie/share/lib/lib_20150513153121/
oozie.wf.application.path=hdfs://localhost:8020/user/oozie/${workflowRoot}
I have specified the path for Apache POI jar file still it is not able to locate it. Please help me to resolve this issue.
Thanks in advance.
can u check the job.property configuration you have mention.
as i know the "${workflowRoot}" parameter should be mentnion in the workflow.xml and job.xml should be defined as the
<property>
<name>workflowRoot</name>
<value>${workflowRoot}</value>
</property>
then try to run the oozie job, belive these will work smoth.
From Oozie MapReduce cookbook:
...Please note that the -libjars option supported by the Hadoop
command-line is not supported by Oozie...
With Oozie, you should instead add a <file> element in the Action to reference the JAR-to-be-downloaded-automagically-in-the-working-dir-of-the-YARN-container-at-run-time.

How to include a property file in WEB-INF folder of war

I am using ant to build my web-app. I am trying to include a property file in the WEB-INF folder from a source folder. I have included it in the war/WEB-APP/classes folder. But the application is not reading it. Hence, i want to include it in the WEB-INF folder directly to read it in the application.
I have tried the following but nothing seems to work. my build.xml looks like this :
<target name="build-dev" description="Package GWT app to web archive and deploy to web server">
<echo message="Package GWT app to web archive" />
<copy toDir="${basedir}/war/WEB-INF/lib">
<fileset dir="${basedir}/lib" includes="*.jar" />
<fileset dir="${gwt.home}" includes="*.jar" />
</copy>
<copy todir="${basedir}/war" file="${basedir}/src/etc/dev/GroupQuoteUI.properties" />
<war basedir="${war.dir}" destfile="${deploy.dir}/${app.name}.war" webxml="${webinf.dir}/web.xml">
<webinf dir="${webinf.dir}/">
<include name="*." />
<exclude name="**/web.xml" />
</webinf>
<classes dir="${basedir}/src/etc/dev/" includes="*.properties" />
</war>
</target>
i have tried to use :
"include name="${war.dir}/GroupQuoteUI.properties" in "webinf" tag but it did'nt worked.
Also includes="${war.dir}/GroupQuoteUI.properties" inside the tag.
Also this inside "webinf" folder again :
"zipfileset dir="${basedir}/war/" includes="GroupQuoteUI.properties" fullpath="${webinf.dir}/GroupQuoteUI.properties"
but this is giving an error during build stating "cannot have src dir together".
So what should i do to include this file in the WEB-INF directory of the war. All other directories and web.xml file is included.
You cannot read a file that is packed into a war, or jar by accessing it with
new FileInputStream()
Instead you can do the following:
this.getClass().getResourceAsStream(filename)
this will load a resource (your properties-file) from the classpath, so it will read the file in a war-archive.
It does this by using the same ClasseLoader which has been used to load the class that belongs to this.getClass()
Here you can find an example:
How to really read text file from classpath in Java

Conditionally include resource in Android (Eclipse) based on project

I am building an Android app in Eclipse and have two similar apps based on the same code base, a 'London' one and a 'UK' one. To build each app, I just re-name the main package and change a static int in the Application class. The app uses the value of this int to display the right UI, restrict user behaviour, etc.
I have two icon files, one for each app:
res/drawable-hdpi/icon_london.png
res/drawable-hdpi/icon_uk.png
Is there any way to conditionally use the correct icon file for the Application and Activities depending upon some sort of project configuration setting? Otherwise, the project maintenance is increased as I would have to change my manifest each time the code base changes, e.g.
<application
android:icon="#drawable/icon_london"
...
>
<activity
android:name="com.company.MainActivity"
android:logo="#drawable/icon_london"
>
</activity>
...and so on, for all the activities.
I had a similar issue, and ended up in building my custon Ant script to build the apps. You can run macros or Regular Expressions to assign one resource or another.
EDIT:
First, add build.xml to the project:
Open up a command prompt and navigate to the directory of your project:
android update project --path
Then, you can override the existing build.xml, for something like the following.
NOTE: This Ant script is just an example, I have not tested it:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Example" default="help">
<property file="local.properties" />
<property file="ant.properties" />
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
unless="sdk.dir"/>
<!-- IMPORT ANT?S BUILD.XML -->
<import file="${sdk.dir}/tools/ant/build.xml" />
<property name="app.icon" value="${icon}" />
<property name="icon.file" location="res/drawable/icon.png" />
<target name="test-release">
<antcall target="test-pre-release" />
<antcall target="release" />
</target>
<target name="test-pre-release">
<copy file="${app.icon}" tofile="${icon.file}" overwrite="true"/>
</target>
</project>
Then, to build this project with a custom icon, open up the command prompt and go to the project directory:
CALL ant -f build.xml test-release -Dicon=path/to/your/icon.png
As said, this is a very basic example. To build a good script, you'll have to learn a bit of Ant syntax, but it's not difficult.

create a .war file from gwt-project

How do I create a .war-file from my gwt-project in eclipse?
I always use Ant build file, so the project gets compiled and packaged as a war with one click.
Add an xml-file to your project with the following content:
<project name="test" basedir="." default="default">
<property name="src.dir" value="src" />
<property name="build.dir" value="war" />
<path id="compile.classpath">
<fileset dir="${build.dir}/WEB-INF/lib">
<include name="**/*.jar" />
<include name="**/*.xml" />
</fileset>
</path>
<target name="default" depends="gwtc, buildwar,deploy">
</target>
<target name="gwtc" description="GWT compile to JavaScript">
<java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
<classpath>
<pathelement location="${src.dir}" />
<path refid="compile.classpath" />
</classpath>
<arg line="-logLevel INFO" />
<jvmarg value="-Xmx1024M" />
<arg value="YourProject.EntryPointClass" />
</java>
</target>
<target name="buildwar">
<war basedir="war" destfile="YourProject.war" webxml="war/WEB-INF/web.xml">
<exclude name="WEB-INF/**" />
<webinf dir="war/WEB-INF/">
<include name="**/gwt-servlet.jar" />
<include name="**/classes/**" />
</webinf>
</war>
</target>
<target name="deploy">
<copy file="YourProject.war" todir="." />
</target>
</project>
(Edit `YourProject.EntryPointClass to the path to your EntryPoint-class)
You would need to add gwt-user.jar and gwt-dev.jarto your projects build path(right click on your project -> Build Path -> Add External Achives).
If you now look at your "Problems"-view you get a warning that the two files are not available on the server's class path. You can use the QuickFix to either copy it to WEB-INF/lib or hide the warning. The build file will not include those two file in the war-file.
All you need to do to compile and create the file is to right click the xml-file and select run as Ant Build.
Using Eclipse:
right click the project
choose Google→GWT Compile
when compilation has finished, the console will say i.e.
Linking into /home/janus/bpworkspace/gwtwerkstatt2/war/gwtwerkstatt2
Link succeeded
Compilation succeeded -- 28.623s
open a terminal and navigate to the directory
create the WAR: jar cv * > /tmp/myGWTproject.war
you can now launch it with jetty-runner or similar: java -jar jetty-runner-8.1.7.v20120910.jar /tmp/myGWTproject.war
I just found this solution, and it's amazing :)
Just install the jar and enjoy extracting to a war file.
Project Site
http://code.google.com/p/gwt-project-export-wizard/
One can also use webAppCreator to generate Ant build file.
webAppCreator ships with GWT SDK and also with Eclipse GWT Plugin. First locate GWT plugin directory
find $HOME/.eclipse/ -name "*gwt*sdk*"
this will output GWT plugin dir path. This dir has gwt dir something like gwt-2.4.0. WebAppCreator will be in this dir. Set this dir as GWTSDK_HOME.
export GWTSDK_HOME=/home/m/.eclipse/org.eclipse.platform_3.7.0_1364963873/plugins/com.google.gwt.eclipse.sdkbundle_2.4.0.v201201120043-rel-r37/gwt-2.4.0
make webAppCreator executable
chmod 755 $GWTSDK_HOME/webAppCreator
Now create a project using webAppCreator in some temp dir.
$GWTSDK_HOME/webAppCreator -out fins in.m.fins.Fins
in.m.fins.Fins is the module name. This has to match with your project's gwt.xml in Eclipse workspace. If your gwt.xml is src/in/m/fins/Fins.gwt.xml then module name should be in.m.fins.Fins
-out fins will create the project and build.xml in fins directory. Copy generated build.xml file to your project in Eclipse workspace.
Run war target in Eclipse Ant Window to package your project as war
You have to have GWT designer installed from here
http://dl.google.com/eclipse/inst/d2gwt/latest/3.7
In Eclipse on the main panel click on "Deploy module on aplication server" (It's next to blue google button).
Chose war file name and location where to store it
Click ok
That's it. Works on my GWT 2.4.0, Google Plugin for Eclipse 4.2, Eclipse Juno
For future reference: you'll find another tutorial on how to create a .war using Eclipse on http://blog.elitecoderz.net/.
Fist compile your project. Then:
1. Open your project.
2. Navigate to war folder.
3. Go to File>Export>Archive File
4. Export your war FOLDER as zip file.
5. Change your file extension form .zip to .war
6. Keep calm and enjoy your war file.
Compile your project. Then:
Open your project.
Navigate to war folder.
Go to File>Export>Archive File
Export your war FOLDER as zip file.
Change your file extension form .zip to .war
Keep calm and enjoy your war file.

Beanshell in Ant yielding, "Unable to create javax script engine for beanshell"

Greeting, I'm trying to put some Beanshell script in my Ant build.xml file. I've followed the Ant manual as well as I can but I keep getting "Unable to create javax script engine for beanshell" when I run Ant. Here is the test target I wrote mostly from examples in the Ant manual:
<target name="test-target">
<script language="beanshell" setbeans="true">
<classpath>
<fileset dir="c:\TEMP" includes="*.jar" />
</classpath>
System.out.println("Hello world");
</script>
</target>
My beanshell "bsh-2.0b4.jar" file is on the script task's classpath the way the manual recommended. Hope I have the right file. I'm working in c:\TEMP right now.
I've been googling and trying for a while now. Any ideas would be greatly appreciated. Thanks.
First, you need jsr-engines.zip from here:
https://scripting.dev.java.net/servlets/ProjectDocumentList
Inside, you'll find jsr223/beanshell/build/bsh-engine.jar. Some searching implied that you need to download bsh-2.05b.jar. I found it here:
http://beanshell.org/bsh-2.0b5.jar
The more easily findable bsh-2.0b4.jar also seemed to work, but it printed a message that implied it was experimental.
Currently (2012) you need only 1 jar to fire the script task for BeanShell:
bsh-2.0b5.jar
Previously I also thought of the following, as mentioned by Ant Manual, Library Dependencies chapter:
bsf-2.4.0.jar
commons-logging-api-1.1.jar
But it looks like bsf is not needed for bsh, at least in my environment.
Once the jar is given to ant, the script task runs smoothly. There are 2 possible scenarios for getting the jars and making them available to ant.
Manual download way
Download the jars above. I provided the links from maven repository. Once you have all the jars downloaded, make them available to ant. There are
at least 3 ways to do it:
Put it in java library path
Put it in ant library directory
Give the correct classpath to script task.
I find the last method the best, because it is most easily ported between
different systems. The ant file for the script task could look as follows:
<project default="t1" >
<property name="bsh.path"
location="/mnt/q/jarek/lang/java/ant/stackoverflow/bsh-2.0b5.jar" />
<target name="t1">
<script language="beanshell" classpath="${bsh.path}">
javax.swing.JOptionPane.showMessageDialog(null, "Hello, Script!");
</script>
</target>
</project>
Automatic download method, employing Ivy
The manual method is not perfect when you want to distribute your build script. Then you would like a way to make sure the jars are present in the destination system. For distributing builds there's no better tool than ivy. Ivy will download the jars and put them in classpath for you. The problem is that there appears another dependency, which is ivy itself. But providing ivy.jar is quite easy and that is the last dependency we need to supply explicitly.
One may ask why to provide ivy.jar, while we could simply download bsh.jar in the same way. The answer is flexibility. When you have the ivy.jar, you get any jar you wish with a single step being adding it to the ivy.xml file. And there is an agreed universal location for the ivy.jar file, while for other file we would have to think of a suitable directory.
Below comes the full example that downloads ivy and then all the necessary dependencies. Ivy download script is based on Installation chapter of Ivy reference.
Then a simple ivy.xml file is needed, which is given after the sample build.xml.
Original auto-download ivy script has a disadvantage of always checking the ivy url, even if ivy.jar is already in the expected location. This may be overriden by specifying -Doffline=true. I prefer to add another target to the build file and to do the http check only if we don't already have the ivy.jar. This is the way the script here works. To observe what ivy actually downloaded, set IVY_HOME environment variable to a directory of your choice. It will be created and filled with ivy stuff.
build.xml:
<project default="t1"
xmlns:ivy="antlib:org.apache.ivy.ant" >
<property name="ivy.install.version" value="2.2.0" />
<property environment="env" />
<condition property="ivy.home" value="${env.IVY_HOME}">
<isset property="env.IVY_HOME" />
</condition>
<property name="ivy.home" value="${user.home}/.ant" />
<property name="ivy.jar.dir" value="${ivy.home}/lib" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<target name="check-ivy">
<condition property="ivy.present">
<available file="${ivy.jar.file}" type="file" />
</condition>
</target>
<target name="download-ivy" unless="ivy.present">
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>
<target name="init-ivy" depends="check-ivy, download-ivy">
<!-- try to load ivy here from ivy home, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
<target name="ivy-libs" depends="init-ivy" >
<ivy:cachepath pathid="path.from.ivy" log="download-only" />
</target>
<target name="t1" depends="ivy-libs" >
<script language="beanshell" classpathref="path.from.ivy">
javax.swing.JOptionPane.showMessageDialog(null, "Hello, Script!");
</script>
</target>
</project>
ivy.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=
"http://ant.apache.org/ivy/schemas/ivy.xsd">
<info organisation="example.com" module="testing-script-task" />
<dependencies>
<dependency org="org.beanshell" name="bsh" rev="2.0b5" />
<!-- <dependency org="bsf" name="bsf" rev="2.4.0" /> -->
</dependencies>
</ivy-module>
The Ant plug-in "org.apache.ant_1.7.0.v200803061910" have all the jar files needed
Don't use beanshell language. Use javascript instead, as it runs on jdk6 without any additional jars. Rebse told me that.
Javascript is also allowed to use java classes, for example java.lang.System.out.println()

Categories