Changing from FileReader to getResourceAsStream - java

When I tried loading my little game from a .jar file the fileReader would no longer work and I was advised to use the getResourceAsStream function instead, when I run the code bellow in the IDE it works fine so the path is correct, when I change to the getResourceAsStream which is currently commented out and remove the file reader line, I get these errors.
Exception in thread "Thread-0" java.lang.NullPointerException
at java.io.Reader.<init>(Reader.java:78)
at java.io.InputStreamReader.<init>(InputStreamReader.java:72)
Is there a way that I can fix this?
public class Utils {
public static String loadFileAsString(String path) {
StringBuilder builder = new StringBuilder();
try{
//InputStream is = Utils.class.getResourceAsStream(path);
//BufferedReader br = new BufferedReader(new InputStreamReader(is));
BufferedReader br = new BufferedReader(new FileReader(path));
String line;
while((line = br.readLine()) != null)
builder.append(line + "\n");
br.close();
}catch(IOException e){
e.printStackTrace();
}
return builder.toString();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/res" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="file://$MODULE_DIR$/res" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" exported="">
<library>
<CLASSES>
<root url="file://$MODULE_DIR$/res/worlds" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

You need to start understanding what you're doing, what the classpath is, how Java loads classes, and how an app is bundled.
When you start a Java program, you use a command looking like this:
java -cp /some/directory:/some/file.jar com.foo.bar.Main
Given the above command, java will try loading the main class (and all the other classes used in your code) in two locations:
the /some/directory directory
the jar file /some/file.jar
Since the class is named Main, and is in the package com.foo.bar, it will thus look for a file named /some/directory/com/foo/bar/Main.class and if it doesn't find it, it will look inside the jar file for an entry /com/foo/bar/Main.class.
When you use SomeClass.getResourceAsStream("/res/worlds/world1.txt"), it will apply the same strategy: look for a file /some/directory/res/worlds/world1.txt and if not found, look inside the jar file for an entry /res/worlds/world1.txt.
So, since you use an IDE to run the project, you need to understand how an IDE works: what command does it use to start your program. The principle is quite simple:
there is a target directory where the IDE puts the .class files it generates from the source .java files. This target directory is part of the classpath when running the program for the IDE
there is also a target directory where the IDE stores all the files that are not .java files, and are located under a directory in IntelliJ marked as "Resources root". This target directory is also part of the classpath.
The structure in the target directory always respects the structure of the source/resource directory.
When packaging the app as a jar file, you'll end up with a jar file containing everything located under these target directories.
By default, in a basic IntelliJ project, your src directory is also a resources root. So every file you put there ends up in the target directory, and is thus available in the classpath, both when launching from the IDE, and when the target directory is packaged as a jar. You should just put the file somewhere under the src directory, and not mess with dependencies. Your txt file is part of the sources of the project, just like a Java file. It's "compiled" by the IDE by copying it to the directory, along with the .class files.

Related

How to point centralized location for multiple workflows in oozie

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

IntelliJ doesn't create jar properly

when I try to build my .jar (as described here) I get a MANIFEST.MF and a xml file inside the artifacts folder that's in the .idea folder. However I have no artifact folder with a .jar file inside the out folder. That's where the .jar file should be. This build process had worked earlier and I have no idea what I messed up.
I really need to build a jar and I used the IntelliJ GUI creator so I can't simply build a jar with an other program because it uses some compiled classes from a IntelliJ library, can I?
The xml file inside the artifacts folder:
<component name="ArtifactManager">
<artifact type="jar" name="Zimmerbelegung_BwInf36:jar">
<output-path>$PROJECT_DIR$/out/artifacts/Zimmerbelegung_BwInf36_jar</output-path>
<root id="archive" name="Zimmerbelegung_BwInf36.jar">
<element id="directory" name="META-INF">
<element id="file-copy" path="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
</element>
<element id="module-output" name="Zimmerbelegung_BwInf36" />
</root>
</artifact>
</component>
My project structure looks like this:
IntelliJ didn't automatically build the artifact.
So I had to build it manually: (Build > Build Artifacts...)

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

Class-Path in jar file with combined libraries

I am trying to create a jar file that is "self contained" concerning the libraries it needs.
Therefore, I created the following ant file:
<project name="srv" default="prod">
<target name="prod">
<jar destfile="build/ServerApplication.jar" basedir="bin/">
<restrict>
<name name="**/*.class"/>
<archives>
<zips>
<fileset dir="lib/" includes="**/*.jar"/>
</zips>
</archives>
</restrict>
<manifest>
<attribute name="Class-Path" value="." />
<attribute name="Main-Class" value="my.package.ServerApplication" />
</manifest>
</jar>
</target>
</project>
But, when I try to launch the application using
> java -jar ServerApplication.jar
I get an error
No suitable driver found for jdbc:mysql://localhost/db?user=root&password=
I reckon this is because the com.mysql.jdbc package inside the jar can't be found. Why is this? When I set the Class-Path to ., shouldn't the jar be able to find all classes inside that jar?
I opened the jar in a decompiler, and all the classes are where they need to be, see here:
What is going wrong here? My MANIFEST looks like this:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.3
Created-By: 1.7.0_07-b10 (Oracle Corporation)
Main-Class: my.package.ServerApplication
Class-Path: .
You must explicitly write the names of the jars if you want them included separated by spaces. Otherwise I would recommend simply launching your jar and providing the class path as a parameter manually:
java -cp . -jar ServerApplication.jar
See here for more information.
I think you should avoid setting classpath at all, and since you are packaging everything in uber-jar - it should work.
Maybe you could try the excellent eclipse plugin which is fatjar.
It had used it many times for including all dependencies of Java Swing based applications.

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.

Categories