Earlier I worked with Pentaho reports, where I can create report with pentaho report designer and deploy .prpt file onto into BI server. It will work fine.
Now I am looking for a solution where I can put .prpt file in a Java program and run just like jasper reports (.jrxml files). Because I need to integrate Pentaho reports with my web application.
I may be asking a very basic question. But I did not find the proper document on this. Please point me to some correct location and a sample code will be helpful.
Since the first link in the accepted answer doesn't seem to work anymore, people who are looking for examples might find this more useful: https://github.com/pentaho/pentaho-reporting/blob/master/engine/samples/source/org/pentaho/reporting/engine/classic/samples
The code in some of the samples is a bit convoluted, so i'm posting my own report generator class, which only contains the bare essentials for generating a PDF report:
public class ReportGenerator {
public byte[] generateReport(byte[] templateBytes, Map<String, Object> params) throws Exception {
ClassicEngineBoot.getInstance().start();
MasterReport reportData = loadTemplateDefinition(templateBytes);
addParametersToReport(params, reportData);
byte[] reportBytes = generateReport(reportData);
return reportBytes;
}
private MasterReport loadTemplateDefinition(byte[] templateBytes) throws Exception {
ResourceManager resourceManager = new ResourceManager();
Resource templateResource = resourceManager.createDirectly(templateBytes, MasterReport.class);
return (MasterReport) templateResource.getResource();
}
private void addParametersToReport(Map<String, Object> params, MasterReport reportData) {
if (params != null) {
for (String key : params.keySet()) {
reportData.getParameterValues().put(key, params.get(key));
}
}
}
private byte[] generateReport(MasterReport reportData) throws ReportProcessingException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfOutputProcessor outputProcessor = new PdfOutputProcessor(reportData.getConfiguration(), outputStream, reportData.getResourceManager());
AbstractReportProcessor reportProcessor = null;
try {
reportProcessor = new PageableReportProcessor(reportData, outputProcessor);
reportProcessor.processReport();
} finally {
if (reportProcessor != null) {
reportProcessor.close();
}
}
return outputStream.toByteArray();
}
}
The generateReport method accepts the contents of a .prpt file in the templateBytes parameter, and a list of parameters needed to generate the report in the params parameter.
The byte array it returns contains the contents of a generated PDF report.
Also if you are using Maven for your application it is important to include all the necessary dependencies. I used the list i found here: http://wiki.pentaho.com/display/Reporting/How+to+integrate+report+designer+to+your+web+application, and in it i replaced all the pentaho-related library versions with version 6.1.0.1-196
I've embedded successfully the Pentaho Reporting Engine in my Java application. There is a tutorial with the necessary libraries and examples. The only thing you need to consider while starting is to use the same version of Pentaho SDK, Pentaho Reporting Engine and Pentaho Report Designer, to don't get datasource issues. If you don't want troubles about dependencies, you can download Pentaho Report Designer and drag and drop all the libraries into your web application (most of the issues come when you try to use pentaho charts, and they are solved in this way).
Official Pentaho Docs:
http://infocenter.pentaho.com/help/index.jsp?topic=%2Freporting_embedders_guide%2Ftopic_embedding_engine.html
Pentaho Reporting Classic Engine Core (better try with this first):
http://sourceforge.net/projects/jfreereport/files/01.%20Classic%20Engine/
Just import all the libraries in your IDE (I used Eclipse Helios), and use the example provided, it will work as a charm!. Then you can start to modify it depending on your needs. I suggest you to review how to handle the path for the reports.
final FacesContext context = FacesContext.getCurrentInstance();
ClassicEngineBoot.getInstance().start();
try {
// load report definition
ResourceManager manager = new ResourceManager();
manager.registerDefaults();
ExternalContext extContext = context.getExternalContext();
String reportPath = "file:" + extContext.getRealPath("name/name.prpt");
Resource res = manager.createDirectly(new URL(reportPath), MasterReport.class);
MasterReport report = (MasterReport) res.getResource();
................
................
httpServletResponse.setContentType("application/rtf");
httpServletResponse.setHeader("Content-Disposition", "attachment; filename=\"name.rtf\"");
RTFReportUtil.createRTF(report, httpServletResponse.getOutputStream());
FacesContext.getCurrentInstance().responseComplete();
} catch (ReportProcessingException ex) {
Related
I'm trying to understand a comment that a colleague made. We're using testcontainers to create a fixture:
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
public class SalesforceFixture extends GenericContainer<SalesforceFixture> {
private static final String APPLICATION_NAME = "salesforce-emulator";
public SalesforceFixture() {
// super(ImageResolver.resolve(APPLICATION_NAME));
super(DockerImageName.parse("gcr.io/ad-selfserve/salesforce-emulator:latest"));
...
}
...
The commented code is what it used to be. The next line is my colleague's suggestion. And on that line he commented:
This is the part I don't know. The [ImageResolver] gets the specific version of the emulator, rather than the latest. You need a docker-info file for that though, which jib doesn't automatically generate (but I think it can).
This is what I know or have figured so far:
SalesforceFixture is a class that will be used by other projects to write tests. It spins up a container in Docker, running a service that emulates the real service's API. It's like a local version of the service that behaves enough like the real thing that if one writes code and tests using the fixture, it should work the same in production. (This is where my knowledge ends.)
I looked into ImageResolver—it seems to be a class we wrote that searches a filesystem for something:
public static String resolve(String applicationName, File... roots) {
Stream<File> searchPaths = Arrays.stream(roots).flatMap((value) -> {
return Stream.of(new File(value, "../" + applicationName), new File(value, applicationName));
});
Optional<File> buildFile = searchPaths.flatMap((searchFile) -> {
if (searchFile.exists()) {
File imageFile = new File(searchFile + File.separator + "/target/docker/image-name");
if (imageFile.exists()) {
return Stream.of(imageFile);
}
}
return Stream.empty();
}).findAny();
InputStream build = (InputStream)buildFile.map(ImageResolver::fileStream).orElseGet(() -> {
return searchClasspath(applicationName);
});
if (build != null) {
try {
return IOUtils.toString(build, Charset.defaultCharset()).trim();
} catch (IOException var6) {
throw new RuntimeException("An exception has occurred while reading build file", var6);
}
} else {
throw new RuntimeException("Could not resolve target image for application: " + applicationName);
}
}
But I'm confused. What filesystem? Like, what is the present working directory? My local computer, wherever I ran the Java program from? Or is this from within some container? (I don't think so.) Or maybe the directory structure inside a .jar file? Or somewhere in gcr.io?
What does he mean about a "specific version number" vs. "latest"? I mean, when I build this project, whatever it built is all I have. Isn't that equivalent to "latest"? In what case would an older version of an image be present? (That's what made me think of gcr.io.)
Or, does he mean, that in the project using this project's image, one will not be able to specify a version via Maven/pom.xml—it will always spin up the latest.
Sorry this is long, just trying to "show my work." Any hints welcome. I'll keep looking.
I can't comment on specifics of your own internal implementations, but ImageResolver seems to work on your local filesystem, e.g. it looks into your target/ directory and also touches the classpath. I can imagine this code was just written for resolving an actual image name (not an image), since it also returns a String.
Regarding latest, using a latest tag for a Docker image is generally considered an anti-pattern, so likely your colleague is commenting about this. Here is a random article from the web explaining some of the issues with latest tag:
https://vsupalov.com/docker-latest-tag/
Besides, I don't understand why you ask these questions which are very specific to your project here on SO rather than asking your colleague.
I am using Spark Framework in my application, and use
staticFileLocation("/META-INF/resources/");
so that I can use webjars, which contain css and js files in there. I also have my own resources put in my projects src/main/resources/META-INF/resources folder because my gradle build picks them up from there.
My build uses a fat-jar approach, where everything ends up in a single jar and all files are served perfectly by Spark.
My problem is that when I run some unit tests standalone from Eclipse, even though I ensured that the webjars are on classpath, they are not served by Spark, only my own project static resources are.
#Test
public void testStartup() throws InterruptedException {
InputStream schemaIS = this.getClass().getClassLoader().getResourceAsStream("META-INF/resources/webjars/bootstrap/3.2.0/js/bootstrap.min.js");
System.out.println(schemaIS == null);
staticFileLocation("/META-INF/resources/");
// depending on the trailing / the bootstrap js is found, but Spark never serves it
}
I think this has something to do with classloaders, but I am not finding the way to make this work. Looking at Spark code, it says The thread context class loader will be used for loading the resource. I also see that the code itself removes the trailing slash, which makes big difference in the plain getResourceAsStream.
Is it a bug in Spark, or is there any way to make it work properly?
Note that removing the leading slash is required by jetty not by Spark.
Unfortunately with Spark you cannot mix static files (in a physical directory/folder) with files served as resources in a jar. And many jars will not work either in Spark.
I had a look at this a few weeks ago and came to a conclusion this is a minor weakness in Spark (or a bug if you may say).
The only way I found out was to reverse Spark and figure out how jetty works. I managed with the following Nashorn javascript snippets to make webjars and static files to work together.
Unless Spark author changes his code to allow inclusion of tailor made context handlers, this will not help you out. But if you wish to pursue in jetty instead, this code with adaptation can help you out.
This code is for Nashorn jjs (from JDK8) but can be easily ported to Java. With this code I was able to use 3 separate webjars jquery/bootstrap/angular and the rest of my client code was in a physical directory/folder public.
app.js:
with(new JavaImporter(
org.eclipse.jetty.server
, org.eclipse.jetty.server.handler
)) {
var server = new Server(4567);
var ctxs = new ContextHandlerCollection();
ctxs.setHandlers(Java.to([
load('src/static.js')
, load('src/webjars.js')
], Handler.class.getName().concat('[]')));
server.setHandler(ctxs);
server.start();
server.join();
}
src/static.js:
(function () {
var context;
with(new JavaImporter(
org.eclipse.jetty.server.handler
, org.eclipse.jetty.util.resource
)) {
context = new ContextHandler();
context.setContextPath("/");
var handler = new ResourceHandler();
handler.setBaseResource(Resource.newResource("public"));
context.setHandler(handler);
}
return context;
})();
src/webjars.js:
(function () {
var context;
with(new JavaImporter(
org.eclipse.jetty.server.handler
, org.eclipse.jetty.util.resource
)) {
context = new ContextHandler();
context.setContextPath("/");
var handler = new (Java.extend(ResourceHandler, {
getResource: function(req) {
var path = req.getUri();
var resource = Resource.newClassPathResource(path);
if (resource == null || !resource.exists()) {
resource = Resource.newClassPathResource("META-INF/resources/webjars" + path);
}
return resource;
}
}))();
handler.setDirectoriesListed(true); // true when debugging, false in production
context.setHandler(handler);
}
return context;
})();
I followed these steps in the hopes of getting storage emulator on localhost working.
I am using Windows 8 RTM.
Downloaded Eclipse and copied it to Program Files.
Installed Java JDK 7.
Installed Azure SDK.
Installed Azure plugin for Eclipse.
Launched storage emulator from the "Start" screen.
Created a Java project.
Added External jars in the build path for Azure to this project.
Wrote this simple sample code:
import com.microsoft.windowsazure.services.blob.client.CloudBlobClient;
import com.microsoft.windowsazure.services.blob.client.CloudBlobContainer;
import com.microsoft.windowsazure.services.core.storage.CloudStorageAccount;
public class AzureStore {
public static final String storageConnectionString = "DefaultEndpointsProtocol=http;"
+ "UseDevelopmentStorage=true;"
+ "AccountName=devstoreaccount1;"
+ "BlobEndpoint=http://127.0.0.1:10000;"
+ "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
public static void main(String[] args) throws Exception {
// Retrieve storage account from connection-string
CloudStorageAccount storageAccount = CloudStorageAccount
.parse(storageConnectionString);
// Create the blob client
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
// Get a reference to a container
// The container name must be lower case
CloudBlobContainer container = blobClient
.getContainerReference("tweet");
try {
// Create the container if it does not exist
System.out.println(container.createIfNotExist());
} catch (Exception e) {
e.printStackTrace();
}
}
}
It gives the following exception:
com.microsoft.windowsazure.services.core.storage.StorageException: The value for one of the HTTP headers is not in the correct format.
at com.microsoft.windowsazure.services.core.storage.StorageException.translateException(StorageException.java:104)
at com.microsoft.windowsazure.services.blob.client.CloudBlobContainer$2.execute(CloudBlobContainer.java:334)
at com.microsoft.windowsazure.services.blob.client.CloudBlobContainer$2.execute(CloudBlobContainer.java:291)
at com.microsoft.windowsazure.services.core.storage.utils.implementation.ExecutionEngine.executeWithRetry(ExecutionEngine.java:110)
at com.microsoft.windowsazure.services.blob.client.CloudBlobContainer.createIfNotExist(CloudBlobContainer.java:339)
at com.microsoft.windowsazure.services.blob.client.CloudBlobContainer.createIfNotExist(CloudBlobContainer.java:257)
at AzureStore.main(AzureStore.java:26)
I am confused at this point, as what might be wrong. Can someone help me?
I think the error is happening because of incorrect storage service version in the API. In your code you're trying to create a blob container in development storage. The "x-ms-version" request header value is sent as "2012-02-12" which though is the latest one but still not supported by the development storage. Development storage still supports "2011-08-18".
If you try your code against cloud storage, you should be able to create that blob container.
If you're only doing your development against development storage, one thing you could do is download the source code from GitHub (https://github.com/WindowsAzure/azure-sdk-for-java/downloads) and modify the following line of code in Constants.java
public static final String TARGET_STORAGE_VERSION = "2012-02-12";
to
public static final String TARGET_STORAGE_VERSION = "2011-08-18";
and compile the source code again. This may break some new functionality introduced in the latest service release (like asynchronous copy blobs etc.)
Other alternative is to wait out for the new SDK to come out and hope that the emulator in that version support the latest storage service version.
More about URI class
See if below works for you.
URI BlobEndPoint = new URI("http://127.0.0.1:10000/devstoreaccount1");
CloudBlobClient bClient = new CloudBlobClient(BlobEndPoint, new StorageCredentialsAccountAndKey(AccountName,
AccountSecurityKey));
I'm working on a web-based application which would allow users to upload a Word document to Google Docs using the GData Java API.
( I came across this blog where I found out that I could actually use a byte array to upload a doc instead of using a File )
I'm using Netbeans + JDK 1.6
The relevant code in my servlet:
DocsService docsService = new DocsService("care.udhc.co.in");
try {
docsService.setUserCredentials("sbose78#gmail.com", "*******");
DocumentListEntry newDocument = new DocumentListEntry();
String s="hello bose";
byte byteData[]=s.getBytes();
// Load the byte array into a MediaSource
MediaByteArraySource mediaSource = new MediaByteArraySource(byteData, MediaType.fromFileName("bose.doc").getMimeType());
MediaContent content = new MediaContent();
content.setMediaSource(mediaSource);
content.setMimeType(new ContentType(mediaSource.getContentType()));
newDocument.setContent(content);
String gdocsFilename = new String("My Filename");
newDocument.setTitle(new PlainTextConstruct(gdocsFilename));
out.println("OK");
// Push it into Google Docs!!
DocumentListEntry uploadedRef = docsService.insert(new URL("https://docs.google.com/feeds/default/private/full/"), newDocument);
} catch(Exception e) {
out.println(e.toString());
} finally {
out.close();
}
When I run it locally, I encounter the following error:
com.google.gdata.util.InvalidEntryException: We're sorry, a server error occurred. Please try again. GDataInvalidEntryExceptionWe're sorry, a server error occurred. Please try again.
When i run the version deployed on the Internet ( Jelastic cloud ),
I get this:
java.lang.NoClassDefFoundError: com/google/gdata/data/extensions/QuotaBytesTotal
com.google.gdata.data.docs.MetadataEntry.declareExtensions(MetadataEntry.java:86)
com.google.gdata.data.ExtensionProfile.addDeclarations(ExtensionProfile.java:71)
com.google.gdata.data.BaseFeed.declareExtensions(BaseFeed.java:235)
com.google.gdata.client.docs.DocsService.declareExtensions(DocsService.java:171)
com.google.gdata.client.docs.DocsService.<init>(DocsService.java:108)
bose.google.UploadToDocs.processRequest(UploadToDocs.java:30)
bose.google.UploadToDocs.doGet(UploadToDocs.java:79)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
Please get me a workaround?
It seems like you are missing one of the required dependencies, probably gdata-core-1.0.jar.
Also, check this page for external dependencies: https://developers.google.com/gdata/articles/java_client_lib
I have been trying to get image resources to display on a GUI I am developing, but am having a difficult time getting them to display. I've come across other questions about loading resources such as java-swing-displaying-images-from-within-a-jar and images-will-not-work-in-a-jar-file, but they aren't working for me.
My issue appears to be the same as the first link, where images appear when run from Eclipse and don't appear when run from the command line using Jars. However the solution to those questions don't make the images appear.
The code I have for retrieving resources is:
public class R {
public static final String resourcePackage = "path/to/image/package";
/**
* Returns the resource string that refers to the <code>resource</code> file
* in the <code>path.to.image.package.png</code> package.
*
* #param resource
* the file in the <code>png</code> package
* #return the full resource string
*/
public static String png(String resource) {
return String.format("%s/png/%s", resourcePackage, resource);
}
public static ResizableIcon resizableIcon(String resource) {
return ImageWrapperResizableIcon.getIcon(R.class.getClassLoader()
.getResourceAsStream(resource), new Dimension(48, 48));
}
}
I call it when generating the GUI
JCommandButton connect = new JCommandButton(i18ln.getString("ports"),
R.resizableIcon(R.png("serial-port-32x32.png")));
A print statement indicates that the resource was found because R.class.getClassLoader().getResourceAsStream returns an instance of sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream.
I'm stumped. I have spent hours trying to figure this out, but could use some help. Any ideas?
FYI: I don't think it matters, but I am using Flamingo for my GUI.
EDIT: per Stefan's request
src/
main/
java/
com.company.project (packages)
R.java
MyGui.java
resources/
com.company.project (packages)
.png (package)
serial-port-32x32.png
(more images)
.i18ln (package)
MyGui.properties
As for more code, I don't know what else I can provide that will be of much benefit for this question. All the code for retrieving resources and how I use that code is provided above. Was there something specific you were looking for?
UPDATE:
When I create a Jar using Eclipse and run it from the command line, the image resources display properly. When I create a Jar using Gradle, the images are not displayed. So there is something being done differently when generating the Jars that allows images resources to be accessed properly via the Eclipse Jar, but not the Gradle Jar. I opened a question on the Gradle forums with respect to this issue.
Dependent on the environment in which your application is (Standalone, ApplicationServer), you will need to use the appropriate ClassLoader.
If you can have a utility class, Utils, you can try something like this:
/* Returns a instance of InputStream for the resource */
public static InputStream getResourceAsStream(String resource)
throws FileNotFoundException {
String stripped = resource.startsWith("/")?resource.substring(1):resource;
InputStream stream = null;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader != null) {
stream = classLoader.getResourceAsStream(stripped);
}
if (stream == null) {
stream = Utils.class.getResourceAsStream(resource);
}
if (stream == null) {
stream = Utils.class.getClassLoader().getResourceAsStream(stripped);
}
if (stream == null) {
throw new FileNotFoundException("Resource not found: " + resource);
}
return stream;
}
For use:
Utils.getResourceAsStream("com/company/project/png/serial-port-32x32.png");
Here try this example HOW TO LOAD IMAGES TO YOUR ECLIPSE PROJECT. Hopefully this will explain things for you, More STEPS HERE
Don't use ClassLoader, thingy though, as described in this Java Doc , A quote from it states "All class loaders will search for a resource first as a system resource, in a manner analogous to searcing for class files."
Forget about the class loader, check the path. If feasible use getResource i.o. getResourceAsStream (question of style: more direct, and delivers null when not found).
As getResource(AsStream) is class based, the paths are relative, so try this:
R.class.getResource("/" + resource)
Create a resources package and place this class and your images in it:
public final class Resources {
public static ImageIcon getImage(String filename) {
URL resourceUrl = Resources.class.getResource(filename);
return new ImageIcon(resourceUrl);
}
}
Edit:
I have rebuild your structure with maven and flamingo (using your R class) and it works with these additions:
Change:
R.class.getClassLoader().getResourceAsStream(resource);
to:
R.class.getResource("png/"+resource);
I have used the maven-assemble-plugin to build the jar as described here.
URL imageurl = getClass().getResource("/images/serial-port-32x32.png");//relative path of the image as argument
Image myPicture = Toolkit.getDefaultToolkit().getImage(imageurl);
Use this Image 'myPicture' as the first argument of ImageWrapperResizableIcon.getIcon method