I'm using Struts2, Spring and Hibernate for my web app.
Now, I'm trying to generate PDF reports with jasper reports struts plugin.
I add the result-type to struts.xml file:
<result-types>
<result-type name="jasper" class="org.apache.struts2.views.jasperreports.JasperReportsResult" default="false"/>
</result-types>
Action definition:
<action name="vf" class="packaget.InvoiceAction" method="seeInvoice">
<result name="success" type="jasper">
<param name="location">/WEB-INF/reports/invoice.jasper</param>
<param name="dataSource">invoiceSource</param>
<param name="format">PDF</param>
<param name="contentDisposition">filename="Invoice.pdf</param>
<param name="documentName">Invoice.pdf</param>
<param name="reportParameters">invoiceParameters</param>
</result>
</action>
And here is my action class:
public class InvoiceAction extends BaseAction implements Preparable {
...
public String seeInvoice(){
List<Invoice> invoice= new ArrayList<Invoice>();
facturas.add(new Invoice());
invoiceParameters.put("message","test");
return SUCCESS;
}
}
I want to generate a download popup, I don't want to see the report in the browser.
How can I force this? contentDisposition or documentName params has no effect...
Thanks in advance.
You have to add "attachment" to the content disposition.
<param name="contentDisposition">attachment</param>
And remove the filename="Invoice.pdf".
This param does the same as documentName. Using them together will duplicate this information in the HTTP response.
<param name="contentDisposition">filename="Invoice.pdf"</param>
Related
I am developing a web application using struts2 .. In that I am downloding a file when user clicks a link ..
When user clicks the link I am checking in my action class whether requested file is existed or not if it is existed then it is working fine ...
WHen it is not existed I am giving a action error message .. But That page is redirecting to error page that i have mapped globally .. IN my console ther is no exception message except these error lines ..
Can not find a java.io.InputStream with the name [fileInputStream] in the invocation stack. Check the <param name="inputName"> tag specified for this action.
And I can see that action message in my error page ... I have debugged the problem also .. Mapping also perfect ..
<action name="downloadAction" class="DownloadPDFAction" method="pdfDownload" >
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename="${downloadDoc}".pdf</param>
<param name="bufferSize">1024</param>
</result>
Is It possible to map back to the same JSP when The file is not existed in SYSTEM .. Thanks
Check whether the file exists or not in the action, and return success & error respectively. You can do something like this :
<action name="downloadAction" class="DownloadPDFAction" method="pdfDownload" >
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename="${downloadDoc}".pdf</param>
<param name="bufferSize">1024</param>
</result>
<result name="error">/error.jsp</result>
error.jsp
<s:actionerror/>
<s:actionmessage/>
or your hard-coded message
But since, you need to go back to the same page, then I suggest calling the download action using ajax and return 200 on success and 204 on error something like this :
<action name="downloadAction" class="DownloadPDFAction" method="pdfDownload" >
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename="${downloadDoc}".pdf</param>
<param name="bufferSize">1024</param>
</result>
<result name="error" type="httpheader">
<param name="status">204</param>
</result>
The ajax call can be something like - docs
$.ajax({
statusCode: {
404: function() {
alert( "page not found" );
},
204: function() {
alert( "file not found" );
}
}
});
In servlets I used
response.sendRedirect("index.jsp?msg=Login failed");
msg after ? to send message while redirecting.
How to do same things with struts2
Since redirection is via struts.xml
<result name="error">/index.jsp</result>
I am just a beginner in struts framework
in your action class which extends ActionSupport:
addActionError("Login failed");
in your index.jsp:
<s:actionerror/>
<result name="error" type="redirect" >
<param name="location">index.jsp?msg=${actionMessage}</param>
<param name="parse">true</param>
<param name="encode">true</param>
</result>
I have multiple actions that after completion redirect back to a general page (showStuff). I'm looking for a way to NOT repeat the list of parameters for every redirect-action.
What I have is this:
<action name="doThis" class="com.domain.package.MyAction" method="doThis">
<result type="redirectAction">
<param name="actionName">showStuff</param>
<param name="parse">true</param>
<param name="selectedYear">${selectedYear}</param>
<param name="selectedMonth">${selectedMonth}</param>
<param name="selectedDay">${selectedDay}</param>
</result>
</action>
<action name="doThat" class="com.domain.package.MyAction" method="doThat">
<result type="redirectAction">
<param name="actionName">showStuff</param>
<param name="parse">true</param>
<param name="selectedYear">${selectedYear}</param>
<param name="selectedMonth">${selectedMonth}</param>
<param name="selectedDay">${selectedDay}</param>
</result>
</action>
I would like to keep the parameter list within the showStuff action definition, and then use is like so:
<action name="doThis" class="com.domain.package.MyAction" method="doThis">
<result type="redirectAction">
<param name="actionName">showStuff</param>
</result>
</action>
<action name="doThat" class="com.domain.package.MyAction" method="doThat">
<result type="redirectAction">
<param name="actionName">showStuff</param>
</result>
</action>
Is it possible?
There are a few options.
Honestly, I'd skip most of my workarounds, and put them into session.
Once they're in session, create an interceptor and interface (Dateable or something). In the interceptor check the session for the variables (see below) and if the action is a Dateable, set them on the action, and you're done.
Another option is to encapsulate these variables as a date and either use the built-in converter or use your own converter. Then you'd only need a single parameter. This option would work with the interceptor idea as well.
As it turns out, it is very much possible. This is how you do it:
Add a global result:
<global-results>
<result name="show-stats" type="redirectAction">
<param name="actionName">showStats</param>
<param name="parse">true</param>
<param name="selectedYear">${selectedYear}</param>
<param name="selectedMonth">${selectedMonth}</param>
<param name="selectedDay">${selectedDay}</param>
</result>
And then for the actions:
<action name="doThis" class="com.domain.package.MyAction" method="doThis"/>
<action name="doThat" class="com.domain.package.MyAction" method="doThat"/>
Finally in the java code, just:
return "show-stats";
And you're done.
As a sidenote, why do I have to spend so much time trying to adhere to the very basic DRY principle? Aren't all these frameworks supposed to .. you know.. simplify stuff? Just wondering...
I was facing the same problem with an endless list of params getting longer and longer, repeated in several places. What I ended up doing was that I created an external file and declared it in struts.xml as an entity then included it instead of repeating all the params
This goes in the doctype tag
<!ENTITY referenceName SYSTEM "fileName">
Then you include it like so
&referenceName;
In my struts2 application i want to define a global configuration part and want to use it where needed.
To clarify let me share one action definiton below;
<action name="do_login" class="xxx.actions.AuthAction" method="doLogin">
<result name="success" type="json">
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="excludeProperties">actionErrors,actionMessages,errorMessages,errors,fieldErrors,locale,texts,action,username,password,errorCode,errorMessage,session</param>
<param name="ignoreHierarchy">false</param>
</result>
<result name="error" type="json">
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="excludeProperties">actionErrors,actionMessages,errorMessages,errors,fieldErrors,locale,texts,action,session</param>
<param name="ignoreHierarchy">false</param>
</result>
</action>
as you can see, in result definitions there are some repeating parts which are;
<param name="noCache">true</param>
<param name="contentType">text/html</param>
<param name="excludeProperties">actionErrors,actionMessages,errorMessages,errors,fieldErrors,locale,texts,action,username,password,errorCode,errorMessage,session</param>
<param name="ignoreHierarchy">false</param>
i want to define this repeating parts globally at the beginning of struts.xml file and use it in each result definition like;
<result name="success" type="json">
{include global definition here}
</result>
i know it is possible to split struts.xml by packages or actions, but i'm wondering it is possible to do above my need?
thx in advance for any response.
Struts2 doesnt have anything for global parameters though they have for global result type,
so you can very well have both success and error as global result and use them.
They have something called as static parameters which is for Action class but not for result type as you need.
How can i redirect www.mysite.com/12345 to www.mysite.com/action?id=12345 using struts2?
I use URL rewriting to get these kind of flexible mappings working (though you could probably do it in struts proper, possibly with your own interceptor or something). There's a great little project, urlrewritefilter that gets the job done. In your URL rewriting configuration you'd have a rule like:
<rule>
<from>^/(\d+)$</from>
<to>/action?id=$1</to>
</rule>
Have a look at the manual to see if it is what you are looking for.
<action name="12345">
<result type="redirect-action">
<param name="actionName">action</param>
<param name="id">12345</param>
</result>
</action>
UPDATE
Ok. Based on the comment below.
I have managed something like this in this way in the past. Create a package in struts with a catch all action.
<package name="numbers">
<action name="*" class="my.package.ActionClass" method="urlrewrite">
<result type="redirect-action">
<param name="actionName">${nextpage}</param>
<param name="id">${id}</param>
</result>
</action>
</package>
Then in the urlrewrite method of the action class:
public String urlrewrite(){
//parse the url and determine the ID and the next page
nextpage = "action";
id = "12345";
return SUCCESS;
}
So in calling the action you will have to do like this:
http://www.mysite.com/numbers/12345.action
If you do not want a new package then you can do this in the default package.