I am creating Jasper reports from My Java Web Application through a pre-designed Jrxml file. the file is in My web folder (Netbeans) in a directory named jrxml so I am trying to get at it using this Method.
public void generateChurchReport(IncomeExpenseBean ieb) {
church = ieb.getChurch();
user = ieb.getUser();
String currdate = dt.getCurrentDate();
Connection conn = db.getDbConnection();
Map parameters = new HashMap();
try{
parameters.put("ChurchName", church);
JasperReport jasperReport = JasperCompileManager.compileReport("/jrxml/ChurchIncome_expenseReport.jrxml");
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, conn);
File f = new File(user + church+ currdate + ".pdf");
JasperExportManager.exportReportToPdfFile(jasperPrint, f.getAbsolutePath());
Desktop.getDesktop().open(new File(f.getAbsolutePath()));
}catch(Exception asd){
System.out.println(asd.getMessage());
}
}
I am getting File Not Found Exception because the Application is expecting the file somewhere in ;
C:\Program Files\glassfish-3.1.2.2\glassfish\domains\TestDom\jrxml\
How do i read this file in my web folder and How can I create the Reports Inside the same folder?
EDIT If I do not give Any Paths My reports are getting Generated at C:\Program Files\glassfish-3.1.2.2\glassfish\domains\TestDom\ if the jrxml file is in that Location.
What you are doing wrong here is, you are trying to locate your jrxml file somewhere in web folder from your java class. This will definitely raise "File Not found error" at run time because of incorrect context path. You could simply do the following:-
Make a folder named say "Jrxml" under your java classes package. Suppose java classes package is com.ejb.beans, make a folder com.ejb.beans.jrxml.
Put all your jrxml files into this folder.
In your java class, load the class loader and locate the jrxml by its name and you will easily access it. Here is the code:-
ClassLoader classLoader = getClass().getClassLoader();
InputStream url = null;
url = classLoader.getResourceAsStream("Report.jrxml");
This url can be used to compile report as :-
JasperReport jasperReport = JasperCompileManager.compileReport(url);
To create the report output file, you could store it at some path in your application server. Set your server path in environment variable and extract it in your class at runtime like this :-
String serverHomeDir = System.getProperty("server.home.dir");
String reportDestination = serverHomeDir + "/domains/ReportOutput/report.html";
// now print report at reportDestination
JasperExportManager.exportReportToHtmlFile(jasperPrint, reportDestination);
Your html file will be generated at the required destination, which you can easily read and render it, the way you want to, through your web page.
Related
This question already has answers here:
Java Jar file: use resource errors: URI is not hierarchical
(6 answers)
Closed 6 years ago.
I have files in resource folder. For example if I need to get file from resource folder, I do like that:
File myFile= new File(MyClass.class.getResource(/myFile.jpg).toURI());
System.out.println(MyClass.class.getResource(/myFile.jpg).getPath());
I've tested and everything works!
The path is
/D:/java/projects/.../classes/X/Y/Z/myFile.jpg
But, If I create jar file, using , Maven:
mvn package
...and then start my app:
java -jar MyJar.jar
I have that following error:
Exception in thread "Thread-4" java.lang.RuntimeException: ხელმოწერის განხორციელება შეუძლებელია
Caused by: java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.<init>(File.java:363)
...and path of file is:
file:/D:/java/projects/.../target/MyJar.jar!/X/Y/Z/myFile.jpg
This exception happens when I try to get file from resource folder. At this line. Why? Why have that problem in JAR file? What do you think?
Is there another way, to get the resource folder path?
You should be using
getResourceAsStream(...);
when the resource is bundled as a jar/war or any other single file package for that matter.
See the thing is, a jar is a single file (kind of like a zip file) holding lots of files together. From Os's pov, its a single file and if you want to access a part of the file(your image file) you must use it as a stream.
Documentation
Here is a solution for Eclipse RCP / Plugin developers:
Bundle bundle = Platform.getBundle("resource_from_some_plugin");
URL fileURL = bundle.getEntry("files/test.txt");
File file = null;
try {
URL resolvedFileURL = FileLocator.toFileURL(fileURL);
// We need to use the 3-arg constructor of URI in order to properly escape file system chars
URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
File file = new File(resolvedURI);
} catch (URISyntaxException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
It's very important to use FileLocator.toFileURL(fileURL) rather than resolve(fileURL)
, cause when the plugin is packed into a jar this will cause Eclipse to create an unpacked version in a temporary location so that the object can be accessed using File. For instance, I guess Lars Vogel has an error in his article - http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/
I face same issue when I was working on a project in my company. First Of All, The URI is not hierarichal Issue is because probably you are using "/" as file separator.
You must remember that "/" is for Windows and from OS to OS it changes, It may be different in Linux. Hence Use File.seperator .
So using
this.getClass().getClassLoader().getResource("res"+File.separator+"secondFolder")
may remove the URI not hierarichal. But Now you may face a Null Pointer Exception. I tried many different ways and then used JarEntries Class to solve it.
File jarFile = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
String actualFile = jarFile.getParentFile().getAbsolutePath()+File.separator+"Name_Of_Jar_File.jar";
System.out.println("jarFile is : "+jarFile.getAbsolutePath());
System.out.println("actulaFilePath is : "+actualFile);
final JarFile jar = new JarFile(actualFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
System.out.println("Reading entries in jar file ");
while(entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
final String name = jarEntry.getName();
if (name.startsWith("Might Specify a folder name you are searching for")) { //filter according to the path
System.out.println("file name is "+name);
System.out.println("is directory : "+jarEntry.isDirectory());
File scriptsFile = new File(name);
System.out.println("file names are : "+scriptsFile.getAbsolutePath());
}
}
jar.close();
You have to specify the jar name here explicitly. So Use this code, this will give you directory and sub directory inside the folder in jar.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have written the following code for creating jasper report, this code working fine in NetBeans IDE, but after creating jar file of that project the report is not opening. Its also not showing any error.
What can be the issue?
Code for creating jasper report
//Path to your .jasper file in your package
String reportSource = "src/report/Allvendor_personal_info.jrxml";
try
{
jasperReport = (JasperReport)
JasperCompileManager.compileReport(reportSource);
jasperPrint = JasperFillManager.fillReport(jasperReport, null, con);
//view report to UI
JasperViewer.viewReport(jasperPrint, false);
con.close();
}
catch(Exception e)
{
JOptionPane.showMessaxgeDialog(null, "Error in genrating report");
}
The path src will not exist at runtime and you should never reference it.
Based on this, the Allvendor_personal_info.jrxml will be an embedded resource, stored within the Jar file, you won't be able to access it like you do normal files, instead, you need to use Class#getResource or Class#getResourceAsStream
String reportSource = "/report/Allvendor_personal_info.jrxml";
InputStream is = null;
try
{
is = getClass().getResourceAsStream(reportSource);
jasperReport = (JasperReport)JasperCompileManager.compileReport(is);
jasperPrint = JasperFillManager.fillReport(jasperReport, null, con);
//...
} finally {
try {
is.close();
} catch (Exception exp) {
}
}
Now, having said that, there should be very little reason to ever compile a .jrxml file at runtime, instead, you should compile these files at build time and deploy the .jasper files instead. This will improve the performance of your application as the complication process is not short even for a basic report.
This would mean you would use...
jasperReport = (JasperReport) JRLoader.loadObjectFromFile(is);
Instead of JasperCompileManager.compileReport
Set environment variables to lib folder of jar files
Well guys, I don't know if It's too late, but I wasted 1 day searching the solutions to this problem, about JasperReport after building an Jar executable. To get your Reports working after building a jar, you just need to write the following lines
String reportUrl = "/reports/billCopyReport.jasper"; //path of your report source.
InputStream reportFile = null;
reportFile = getClass().getResourceAsStream(reportUrl);
Map data = new HashMap(); //In case your report need predefined parameters you'll need to fill this Map
JasperPrint print = JasperFillManager.fillReport(reportFile, data, conection);
JasperViewer Jviewer = new JasperViewer(print, false);
Jviewer.setVisible(true);
/* var conection is a Connection type to let JasperReport connecto to Database, in case you won't use DataBase as DataSource, you should create a EmptyDataSource var*/
you need to copy folder which has jasper/Jrxml files and put it same directory of your jar file.
whenever you write code like this
String reportSource = "/report/Allvendor_personal_info.jrxml";
//It will look for this file on your location so you need to copy your file on /report/ this location
InputStream is = null;
try
{
is = getClass().getResourceAsStream(reportSource);
jasperReport = (JasperReport)JasperCompileManager.compileReport(is);
jasperPrint = JasperFillManager.fillReport(jasperReport, null, con);
//...
} catch(Exception e){
}
I have created an application which does some job and it has a configuration folder inside it(named /xml/Configuration.xml).Now, I am trying to use the same jar in multiple projects and the only change which I want to make it is by changing the configuration file contained within the jar file.
String xmlConfigPath = System.getProperty(user.dir) + File.separator
+ "xml" + File.separator + "Configuration.xml";
As you can see here, I access the XML file by using the "user.dir" followed by the complete file name.This(user directory) obviously will change when the jar added in a project is run from a different user.dir which hence does not find the Configuration.xml file placed inside the jar file added to my project.
Is there a way to make this jar access its own configuration folder irrespective of which project or location its placed in?
Please see the following code
Inside my jar file I have the following function which loads the configuration
/**
* This method is responsible for reading the EMail Configuration
* #return <MailSender>
* #throws Exception
*/
private static MailSender getConfig(String configPackagePath, String fileName) throws Exception {
JAXBContext jaxbContext;
Unmarshaller unmarshaller;
StreamSource source;
JAXBElement<MailSender> mailSenderElement;
MailSender mailSenderConfig = null;
String xmlConfigPath = getUserDirectoryPath() + File.separator
+ ApplicationConstants.XML + File.separator + fileName;
try {
jaxbContext = JAXBContext.newInstance(configPackagePath);
File file = new File(xmlConfigPath);
unmarshaller = jaxbContext.createUnmarshaller();
source = new StreamSource(file);
mailSenderElement = unmarshaller.unmarshal(source, MailSender.class);
mailSenderConfig = mailSenderElement.getValue();
} catch (JAXBException e) {
String errorMessage = "Error encountered while reading the EMail XML Configuration file at " + xmlConfigPath;
throw new Exception(errorMessage, e);
}
return mailSenderConfig;
}
/**
* This method is responsible for fetching the User Directory Path
* #return <String> userDirectoryPath
*/
private static String getUserDirectoryPath() {
return System.getProperty(ApplicationConstants.USER_DIR);
}
Now, while running this as a standalone project, it finds the correct path and works fine.Now, when I package this as a jar, this fails because it cannot fetch the file from the current user directory.The intention here is I want the jar file to use absolute path to access the file already placed inside it without having anything to do with the location of where it(jar file) might itself be placed.
You should instead put the configuration file on the classpath of your application and load it using ClassLoader.getResourceAsStream
This means for example using xml/ as source folder inside Eclipse, then you can get the configuration file from anywhere using :
getClass().getResourceAsStream("/xml/Configuration.xml");
Some suggestions:
use Classpath for accessing your config file. See more info here How to really read text file from classpath in Java
use absolute path
use path traversal with ../.. (up to one level)
If the file is within the JAR file then you should use something like:
File conf=new File(getClass().getResource("/xml/Configuration.xml").toURI());
// The "absolute path" here points at the root of the JAR
In My Java app, i have structure like this,
sip
build
dist
nbproject
src
sip
Form.java
schedule.jrxml
test
And this my code to load jrxml in Form.java
try{
//String schedule_all ="E:\\My Data\\Tugas Akhir\\repos\\sip\\src\\sip\\jadwal.jrxml";
InputStream file = this.getClass().getClassLoader().getResourceAsStream("/sip/schedule.jrxml");
JasperReport jr= JasperCompileManager.compileReport(file);
JasperPrint jp = JasperFillManager.fillReport(jr, null,con);
JasperViewer jv = new JasperViewer(jp,false);
jv.setVisible(true);
}
catch(Exception e){
JOptionPane.showMessageDialog(null,"Error show Document");
tambah_log(e.toString());
}
I Want to replace this path(E:\My Data\Tugas Akhir\repos\sip\src\sip\jadwal.jrxml";)
to my local project path like this ("/sip/jadwal.jrxml").
but i got this error
net.sf.jasperreports.engine.JRException:
java.net.MalformedURLException
Any Idea? Because i want deploy my system to another computer. And i wont configure its path again.
FIXED
I change My Code like this.
InputStream file = this.getClass().getClassLoader().getResourceAsStream("/sip/jadwal.jrxml");
JasperReport jr= JasperCompileManager.compileReport(System.getProperties().getProperty("java.class.path").split(";")[System.getProperties().getProperty("java.class.path").split(";").length - 1]+"\\sip\\jadwal.jrxml");
JasperPrint jp = JasperFillManager.fillReport(jr, null,con);
JasperViewer jv = new JasperViewer(jp,false);
jv.setVisible(true);
Your getResourceAsStream("/sip/schedule.jrxml"); call doesn't accept that type of "URL"
Check the documentation, if its a local file it probably wants "file:///C:/path/to/whereever/sip/schedule.jrxml"
Or you could see the solution posted here: https://community.oracle.com/thread/620656?start=0&tstart=0
Or better yet here
http://forum.spring.io/forum/spring-projects/container/62863-how-to-use-getresourceasstream-to-get-a-file-stream
In windows operating systems java accepts the drive having the os installation as root directory. If you put your /sip directory to that drive, for example (and generally) to C drive. Then you can reach it as
this.getClass().getClassLoader().getResourceAsStream("/sip/schedule.jrxml"); .
Putting the schedule.jrxml to a package or to a resource folder of the project is a better practice though, because in this case you may install it anywhere you want.
Is there a way for java program to determine its location in the file system?
You can use CodeSource#getLocation() for this. The CodeSource is available by ProtectionDomain#getCodeSource(). The ProtectionDomain in turn is available by Class#getProtectionDomain().
URL location = getClass().getProtectionDomain().getCodeSource().getLocation();
File file = new File(location.getPath());
// ...
This returns the exact location of the Class in question.
Update: as per the comments, it's apparently already in the classpath. You can then just use ClassLoader#getResource() wherein you pass the root-package-relative path.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL resource = classLoader.getResource("filename.ext");
File file = new File(resource.getPath());
// ...
You can even get it as an InputStream using ClassLoader#getResourceAsStream().
InputStream input = classLoader.getResourceAsStream("filename.ext");
// ...
That's also the normal way of using packaged resources. If it's located inside a package, then use for example com/example/filename.ext instead.
For me this worked, when I knew what was the exact name of the file:
File f = new File("OutFile.txt");
System.out.println("f.getAbsolutePath() = " + f.getAbsolutePath());
Or there is this solution too: http://docs.oracle.com/javase/tutorial/essential/io/find.html
if you want to get the "working directory" for the currently running program, then just use:
new File("");