Spring MVC 3.0 Jasper-Reports 4 Directing HTML reports in browser - spring-mvc

I am working with Spring MVC 3 and JasperReports. I've created some great PDF and Xls reports without a problem. What I would like to do is display the created HTML report on screen for the user as a preview of the report they are getting, wrapped in the website template. Is there a way to do this?
I haven't found any tutorials/articles on this subject, I did find a book on JasperReports 3.5 for Java Developers that kind a addressed this. (I'm a noob on this so bear with me.) My understanding of this is that I have to redirect the input stream to the browser. I figure that there must be an easier way! And a way to strip the HTML report header and footer from it.
Any help would be appreciated!

Instead of using another framework to solve my problem. I solved it like this:
#RequestMapping(value = "/report", method = RequestMethod.POST)
public String htmlReport(#RequestParam(value = "beginDate") Date begin,
#RequestParam(value = "endDate", required = false) Date end,
ModelMap map) {
try {
// Setup my data connection
OracleDataSource ds = new OracleDataSource();
ds.setURL("jdbc:oracle:thin:user/password#10.10.10.10:1521:tst3");
Connection conn = ds.getConnection();
// Get the jasper report object located in package org.dphhs.tarts.reports
// Load it
InputStream reportStream = this.getClass().getResourceAsStream("reports/tartsCostAllocation.jasper");
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(reportStream);
// Populate report with data
JasperPrint jasperPrint =
JasperFillManager.fillReport(jasperReport, new HashMap(), conn);
// Create report exporter to be in Html
JRExporter exporter = new JRHtmlExporter();
// Create string buffer to store completed report
StringBuffer sb = new StringBuffer();
// Setup report, no header, no footer, no images for layout
exporter.setParameter(JRHtmlExporterParameter.HTML_HEADER, "");
exporter.setParameter(JRHtmlExporterParameter.HTML_FOOTER, "");
exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE);
// When report is exported send to string buffer
exporter.setParameter(JRExporterParameter.OUTPUT_STRING_BUFFER, sb);
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
// Export the report, store to sb
exporter.exportReport();
// Use Jsoup to clean the report table html to output to browser
Whitelist allowedHtml = new Whitelist();
allowedHtml.addTags("table", "tr", "td", "span");
allowedHtml.addTags("table", "style", "cellpadding", "cellspacing", "border", "bgcolor");
allowedHtml.addAttributes("tr", "valign");
allowedHtml.addAttributes("td", "colspan", "style");
allowedHtml.addAttributes("span", "style");
String html = Jsoup.clean(sb.toString(), allowedHtml);
// Add report to map
map.addAttribute("report", html);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "costallocation/report";
}

Related

scraping html without htmlagilitypack

Due to the limitation of the system, i am not allowed to use htmlagilitypack as i dont have the rights to refer the library. So i can only use native asp.net programming language to parse page.
e.g. i want to scrap this page https://sg.linkedin.com/job/google/jobs/ to get the list of google jobs ( just an example, i am not really planning to get this list but my own company's) , i see they are under how can i extra these jobs description and name.
My current codes are
System.Net.WebClient client = new System.Net.WebClient();
try{
System.IO.Stream myStream = client.OpenRead("https://sg.linkedin.com/job/google/jobs/");
System.IO.StreamReader sr = new System.IO.StreamReader(myStream);
string htmlContent = sr.ReadToEnd();
//do not know how to carry on
}catch(Exception e){
Response.Write(e.Message);
}
how can i carry on?
You can fetch that page and use a regular expression to isolate the useful parts. If you get real lucky, you may have a valid XML file:
var html = new WebClient().DownloadString("https://sg.linkedin.com/job/google/jobs/");
var jobs = new XmlDocument();
jobs.LoadXml(Regex.Replace(Regex.Match(html,
#"<ul class=""jobs"">[\s\S]*?</ul>").Value,
#"itemscope | itemprop="".*?""", "")); // clean invalid attributes
foreach (XmlElement job in jobs.SelectNodes("//li[#class='job']"))
{
Console.WriteLine(job.SelectSingleNode(".//a[#class='company']").InnerText);
Console.WriteLine(job.SelectSingleNode(".//h2/a").InnerText);
Console.WriteLine(job.SelectSingleNode(".//p[#class='abstract']").InnerText);
Console.WriteLine();
}

need to automate the RDLC reporting through SSIS script task?

Currently I'm calling RDLC report in asp.net application, where .rdlc is calling and we passing a data source and report in generated as PDF, the entire process initiate on a BUTTON click and report is generate.
Now this process need to automate and report should generate on Monday morning.
There is some suggestion come out that we can use SSIS Script Task and we can call external DLL and can call .rdlc file too to generate the report and then we can schedule SSIS package?
I never having experience on SSIS side, need your suggestion and how to do that, if there is possibilities? Thank You!
Use SSRS to schedule the report to run. No need for ASP.net or SSIS, SSRS has scheduling built in.
You can use SSRS subscription to send the report. If you really want the SSIS to send the report. you can do the following.
Create the report in SSRS
Deploy the report into report server
Create the SSIS package
Drag your Script task into the package.
You could use the following code snippet to send SSRS report using SSIS.
You should create some of the SSIS variables to store the report and render information.
RenderExtension ==> pdf
RenderFileName ==> Name of the file you want write
RenderFormat ==> PDF
RenderOutputPath==> Location to write the file
SSRSConnection ==>
http://localhost/ReportServer/reportexecution2005.asmx [Location of
your report services]
SSRSFolderName ==> Folder name of the report you deployed
SSRSReportName ==> Name of the report
In the following snippet.
public void Main()
{
var rExtension = Dts.Variables["RenderExtension"].Value.ToString();
var rFileName = Dts.Variables["RenderFileName"].Value.ToString();
var rFormat = Dts.Variables["RenderFormat"].Value.ToString();
var rOutputPath = Dts.Variables["RenderOutputPath"].Value.ToString();
var ssrsConnection = Dts.Variables["SSRSConnection"].Value.ToString();
var ssrsFolderName = Dts.Variables["SSRSFolderName"].Value.ToString();
var ssrsReportName = Dts.Variables["SSRSReportName"].Value.ToString();
ReportExecutionService rs=new ReportExecutionService();
Byte[] results;
string encoding = string.Empty;
string mimetype = string.Empty;
string extension = string.Empty;
Warning[] warnings = null;
string[] streamId = null;
string deviceInfo = null;
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
rs.Url = ssrsConnection;
try
{
var reportpath = string.Format("/{0}/{1}", ssrsFolderName, ssrsReportName);
rs.LoadReport(reportpath, null);
//Adding Parameters
//Commenting the following line Till we test the functionality
ParameterValue[] paramValues = new ParameterValue[4];
ParameterValue paramValue = new ParameterValue();
paramValue.Name = "ReportParamName";
paramValue.Value = "X,Y,Z";
paramValues[0] = paramValue;
rs.SetExecutionParameters(paramValues, "en-US");
results = rs.Render(rFormat, deviceInfo, out extension, out mimetype, out encoding, out warnings, out streamId);
var filewithdatetime = string.Format("{0}_{1}",rFileName,DateTime.Now.ToString("yyyy_MM_dd_hhmmss"));
string path = string.Format(#"{0}\{1}.{2}", rOutputPath, filewithdatetime, rExtension);
MessageBox.Show(path);
using (FileStream stream = File.OpenWrite(path))
{
stream.Write(results, 0, results.Length);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
}
Dts.TaskResult = (int)ScriptResults.Success;
}

Lose HttpServletRequest Parts After Reading Them

I have a servlet that receives an uploaded file. We've been having issues with a certain client's request not having a file attached or so the servlet thinks. The upload servlet is a replacement for an old one and we're using the Apache Commons FileUpload library to parse the file from the request. The old code uses the JavaZoom library. The requests client we're having issues with work perfectly fine in the old code.
In order to troubleshoot the problem, I added a bunch of logging to look at the request headers and parts to compare requests from a client that works with the one that doesn't. This is a snippet of how I'm looking at the parts:
Collection<Part> parts = request.getParts();
for(Part part : parts)
{
String partName = part.getName();
log.debug("Part=" + partName);
Collection<String> headerNames = part.getHeaderNames();
for(String headerName : headerNames)
{
String headerValue = part.getHeader(headerName);
log.debug(headerName + "=" + headerValue);
InputStream inputStream = part.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
StringBuilder builder = new StringBuilder();
try
{
for(String line=bufferedReader.readLine(); line!=null; line=bufferedReader.readLine())
{
builder.append(line);
builder.append('\n');
}
}
catch (IOException ignore)
{
// empty
}
finally
{
inputStream.reset();
}
log.debug("InputStream=" + builder.toString());
}
}
All this code works fine and I get the logging I'm expecting. However, this next bit of code doesn't act as expected:
if (isMultipart)
{
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
#SuppressWarnings("rawtypes")
List items = null;
// Parse the request
try
{
items = upload.parseRequest(request);
log.debug("items=" + items);
}
catch (FileUploadException ex)
{
log.warn("Error parsing request", ex);
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
}
the items variable is empty when it's logged. If I comment out the code for logging the request parts, this bit of code works and the items variable contains the uploaded file.
I can only assume that the act of getting/reading the parts from the request somehow removes them from it and are no longer available for further processing. Is there some way to read them for logging purposes and still retain them in the request for further processing?
The Collection<Part> parts = request.getParts(); is an Sevlet 3.0 API which is replacement for Commons Apache File Upload API.
You should be using only one of the two methods. Both have the support for processing uploaded files and parameters along with it.
Here is the Example for File Upload Using Servlet 3.0
The problem you are facing is because you are invoking this Collection<Part> parts = request.getParts(); request will consume the request input stream. And then you are using Apache Commons API to read the parts again. Because the stream is already read you are seeing no parts are available.
References for Servlet 3.0 File Upload:
Posting Data along with File
Servlet 3.0 Multipart Example
Servlet 3.0 MultipartConfig

adding dynamic message at end of flash video

I am working on a Flash training video. I would like at the end of the video for a message to pop up with a dynamic confirmation code. I have the code for the confirmation code, but am having trouble creating something either at the end of the flash video or within the aspx page to trigger this message. Any thoughts or ideas of how to solve this would be greatly appreciated.
Thank You.
Depend on the purpose of the application, you can do either one. One thing to consider is does the user has to go through the flash video to obtain the code. If so, you need to organize the flow of the application in a way that the user can't cheat their way to obtain the code.
The ideal way is to have the flash called aspx page at the end of the movie to obtain the dynamic code. This can be done using URLLoader in ActionScript 3.0 or LoadVars in ActionScript 2.0.
URLLoader example
//this is the data
var data = "This is data";
//url of your aspx code
var request:URLRequest = new URLRequest("http://www.yourdomain.com/GenerateCode.aspx");
request.contentType = "text/xml";
request.data = data;
//use POST method
request.method = URLRequestMethod.POST;
var loader:URLLoader = new URLLoader();
try
{
//execute the request
loader.load(request);
}
catch (error:ArgumentError)
{
trace("There is an ArgumentError.");
}
LoadVars example:
//create LoadVars object
var lv_in:LoadVars = new LoadVars();
var lv_out:LoadVars = new LoadVars();
//set onLoad event
lv_in.onLoad = function(success:Boolean)
{
//if success, meaning data has received response from .net page, run this code
if (success)
{
//lv_in.status is use to get the posted data from .Net page
statusMsg.text = "Thank you!" + lv_in.status;
}
//if fail, run this code
else
{
statusMsg.text = "Error!";
}
}
//this is the data
lv_out.data = "This is data";
//begin invoke aspx page
lv_out.sendAndLoad("GenerateCode.aspx", lv_in, "POST");
There another easier way but not the best practice i should say. The easier way would be to direct user to aspx page that generate dynamic code after users finish the flash movie. The negative side is, the page can be accessed although users did not finish the flash movie.

How do I stream .flv files from SQL database

I want to store .flv files in the database and not in the file system.
This is what I can do right now:
Successfully convert .wmv and .mpeg to .flv with ffmpeg.
Store images in SQL Server and show them on my page with an httphandler.
Same with .avi and .mpeg videos. (It's up to the user's software if he can view it though)
Play .flv files in the browser if the file is located in the file system and not in the database.
What I can't do is:
Stream .flv videos to JW Player directly from the database. (Stored as binary data)
I've searched the internet for two days now but I can't get it to work. It feels as if I'm almost there though. The JW Player opens up and starts to "buffer", but nothing happens.
I know there's no easy answer but if anyone has done this before, or something similar, I'd like to know how you did. I feel I've got too much code to post it all here.
Thanks in advance!
I got it to work but I have no idea as to how efficient it is. Is it better to stream from the file system than from the database in terms of connections, efficency, load etc.
I could use some pointers on this!
I'm using JW Player here, hence "swfobject.js" and "player.swf"
httpHandler:
public class ViewFilm : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
try
{
// Check if id was given
if (context.Request.QueryString["id"] != null)
{
string movId = context.Request.QueryString["id"];
// Connect to DB and get the item id
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString))
using (SqlCommand cmd = new SqlCommand("GetItem", con))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter sqlParam = cmd.Parameters.Add("#itemId", SqlDbType.Int);
sqlParam.Value = movId;
con.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr.HasRows)
{
dr.Read();
// Add HTTP header stuff: cache, content type and length
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetLastModified(DateTime.Now);
context.Response.AppendHeader("Content-Type", "video/x-flv");
context.Response.AppendHeader("Content-Length", ((byte[])dr["data"]).Length.ToString());
context.Response.BinaryWrite((byte[])dr["data"]);
}
}
}
}
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
public bool IsReusable
{
get { return false; }
}
}
javascript
The function adds a player to <div id="video1"> and can be called e.g when a user clicks a button.
<script type='text/javascript' src='swfobject.js'></script>
<script type="text/javascript" language="javascript">
function vid() {
var s1 = new SWFObject('player.swf', 'player1', '480', '270', '9');
s1.addParam('allowfullscreen', 'true');
s1.addParam('allowscriptaccess', 'always');
s1.addVariable('file', encodeURIComponent('ViewFilm.ashx?id=10'));
s1.addVariable('type', 'video');
s1.write(document.getElementById("video1"));
}
</script>
Not sure exactly how literally to take "stream directly from the database", but would it work to set the source "file" for the JW Player to "ServeFLV.aspx?id=123", and have ServeFLV.aspx retrieve the bytes from the database, and write them out to the response with no markup?
If you're using SQL Server 2008 you could use varbinary(MAX) FILESTREAM which would allow the files to be managed by the database but still give you access to a FileStream from .NET.

Resources