I am trying to download a csv file on click of a button. I have the following implementation, but the moment I click the button, I get a page expired message
WebResource export = new WebResource() {
#Override
public IResourceStream getResourceStream() {
StringBuffer result = new StringBuffer();
for(Person person: tmpList){
result.append(person.toCSV()).append("\n");
}
return new StringResourceStream(result, "text/plain");
}
#Override
protected void setHeaders(WebResponse response) {
super.setHeaders(response);
response.setAttachmentHeader("person.csv");
}
};
export.setCacheable(false);
form.add(new ResourceLink("exportLink", export));
my html markup is as follows
<a wicket:id="exportLink"><button class="button">Export</button></a>
The error was because of serialization. one of the classes were not serialized
Related
I have a component which allows a user to download an excel file after clicking a link.
It works and everything is fine, but I don't know how to write a test for this component.
I want to write a test to check if after pressing a link a file is sent to a client.
And so, my component looks like this
Link<Void> calculationsLink = new Link<>("calculationsLink") {
#Override
public void onClick() {
AbstractResourceStreamWriter rStream =
new AbstractResourceStreamWriter() {
#Override
public void write(OutputStream output)
throws IOException {
output.write(MyApp.class
.getResourceAsStream(pathToCalculations)
.readAllBytes());
}
};
ResourceStreamRequestHandler handler =
new ResourceStreamRequestHandler(rStream, "calculations.xslx");
getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
}
};
My test is
#Test
public void calculations_file_downloaded_Successfully() {
// then start and render the base page
tester.startPage(HomePage.class); <-- link is located in a HomePage
tester.clickLink("navBar:calculations", false); <-- link is clickable
tester.getResponse();//????
tester.assert???(?????); <-- how to assert and what to assert?
}
You should use tester.getLastResponse() and assert on its properties.
tester.getResponse() is the MockHttpServletResponse that will be used for the next HTTP call.
Some dummy examples:
assertEquals("application/octet-stream", tester.getLastResponse().getContentType());
assertEquals(3, tester.getLastResponse().getBinaryContent().length);
assertArrayEquals(new byte[] {1, 2, 3}, tester.getLastResponse().getBinaryContent());
I am trying to do the following on AEM 6.1:
Develop a simple form (3 input fields)
Process the submitted values,
And redirect to the same page with processed values/result
I am able to submit the values to a servlet, and process them (business logic), and the result to a requestparamter so i can retrieve them on the UI. But i am stuck at these:
Redirecting to the same page
And retrieving the request parameters and display them using Sightly.
Code Snippets:
Servlet
#SlingServlet(
methods = { "POST","GET" },
name="com.tti.tticommons.service.servlets.LeadTimeTrendsServlet",
paths = { "/services/processFormData" }
)
public class TTICommonServlet extends SlingAllMethodsServlet{
...
#Override
protected void doPost(SlingHttpServletRequest request,SlingHttpServletResponse response) throws ServletException,IOException {
String result;
try {
Enumeration<String> parameterNames = request.getParameterNames();
Map<String, String> formParametersMap = new HashMap<String, String>();
while (parameterNames.hasMoreElements()) {
paramName = parameterNames.nextElement();
paramValue = request.getParameter(paramName);
.......
.......
}
request.setAttribute("result",result);
response.sendRedirect("/content/ttii/en/**posttest.html**");
}
}
Can anyone please help on ho to retireve the above "result" in posttest.html using sightly.
After lot of research and several trials, i finally had the code working. I had to pick up related info from several answers in stackoverflow. Thanks to all the authors. Posting my solution here so beneficial for others.
Result Form with response from webservice:
Process flow
Submit form data to Servlet's POST method
In Servlet, get the values entered by the user from the request
Make the necessary webservice calls. Get the response(json)
I added the response-json as a parameter to the request
Using Wrapper, forward to the necessary page
Define a WCMUse class for use with Sightly.
Assign the 'request' to the Use-class and process it there
Use the assigned values from the Use-class to the UI using sightly
Code snippets - HTML
<form name="userRegistrationForm" method="post" action="/services/processFormData">
<input type="hidden" name=":redirect" value="posttest.html" />
<input type="submit" title="Submit" class="btn submit btn-success" value="Submit" tabindex="25" name="bttnAction">
<div data-sly-use.model="${'com.abccommons.service.helpers.PostServiceHelper' # slingreq=request }">
**${model.getRawJson}**
</div>
Code snippets - Servlet
#SlingServlet(
label = "ABC - Common Servlet",
metatype = true,
methods = { "POST" },
name="com.abccommons.service.servlets.ABCPostServlet",
paths = { "/services/processFormData" }
)
public class ABCPostServlet extends SlingAllMethodsServlet{
#Override
protected void doPost(SlingHttpServletRequest request,SlingHttpServletResponse response) throws ServletException,IOException {
log.info("\n\n----- ABCPostServlet POST: ");
String paramName;
String paramValue;
String osgiService="";
try {
Enumeration<String> parameterNames = request.getParameterNames();
Map<String, String> formParametersMap = new HashMap<String, String>();
while (parameterNames.hasMoreElements()) {
paramName = parameterNames.nextElement();
paramValue = request.getParameter(paramName);
if (paramName.equals("osgiService")) {
osgiService = paramValue;
} else if (paramName.equals(":cq_csrf_token")) {
//TODO: don't add to the map
} else if (paramName.equals("bttnAction")) {
//TODO: dont' add to the map
} else {
//log.info("\n---ParamName="+paramName+", value="+paramValue);
formParametersMap.put(paramName, paramValue);
}
}
String parametersInJSON = JSONHelper.toJson(formParametersMap);
log.info("\n\n----------- POST paramters in json="+parametersInJSON);
String json = webServiceHelper.getJSON(osgiService, parametersInJSON, request, response);
log.info("\n\n----------- POST json from web service="+json);
request.setAttribute("jsonResponse",json);
//String redirectPage = request.getParameter(":redirect");
//RequestDispatcher dispatcher = request.getRequestDispatcher("/content/en/"+redirectPage);
RequestDispatcher dispatcher = request.getRequestDispatcher("/content/en/postformtest.html");
GetRequest getRequest = new GetRequest(request);
dispatcher.forward(getRequest, response);
} catch (Exception e) {
log.error("SlingServlet Failed while retrieving resources");
} finally {
//TODO
}
}
/** Wrapper class to always return GET for AEM to process the request/response as GET.
*/
private static class GetRequest extends SlingHttpServletRequestWrapper {
public GetRequest(SlingHttpServletRequest wrappedRequest) {
super(wrappedRequest);
}
#Override
public String getMethod() {
return "GET";
}
}
Code snippets - PostServiceHelper - WCMUSe class
public class PostServiceHelper extends WCMUse {
protected final Logger log = LoggerFactory.getLogger(PostServiceHelper.class);
private SlingHttpServletRequest httpRequest;
private String rawJson;
#Override
public void activate() throws Exception {
log.info("\n\n========= PostServiceHelper.activate():"+get("slingreq", SlingHttpServletRequest.class));
this.httpRequest = get("slingreq", SlingHttpServletRequest.class);
//this.resourceResolver = getResourceResolver();
//log.info("\n\n========= getRequest()="+getRequest());
SlingHttpServletRequest tRequest;
Set<String> keys = new HashSet<String>();
Enumeration<?> attrNames = this.httpRequest.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attr = (String) attrNames.nextElement();
//log.info("\n--- Key="+attr);
if (attr.equals("jsonResponse")) {
this.setRawJson((String)this.httpRequest.getAttribute(attr));
//log.info("\n---rawJson is SET with : "+this.rawJson);
}
}
}
public void setRawJson(String json) {
this.rawJson = json;
}
public String getRawJson() {
return this.rawJson;
}
}
This is actually a rather tricky pattern to achieve in Sling. You may be better served by submitting the form asynchronously and updating your HTML dynamically via JavaScript.
If you do need to submit your form in the manner you specify, then your servlet needs to produce the HTML response. To produce a response made up of a rendering of the page identified by the requested path your servlet will need to dispatch the request to the appropriate rendering mechanism. You can reference Get JSP output within Servlet in AEM for information concerning how that can be accomplished. Upon dispatch your page and its components should have access to the submitted form values as well as the attributes set on the request.
I need little help to achieve this, in my app user can upload files to server and its stored as blob object, and now i need to show them to user up on there request.
What I am up to is show in below code,
On server side I put content to response:
(This code is implemented based on this blog post WaterTalks)
resp.setContentType("text/plain");
resp.setHeader("Content-Disposition", "attachment; filename=output.txt");
PrintWriter out = resp.getWriter();
out.println("This is the output content");
out.println("Probably something dynamic should go in here:::::");
PersistenceManager pm = null;
try {
pm = PMF.get().getPersistenceManager();
javax.jdo.Transaction transaction = pm.currentTransaction();
Extent e = pm.getExtent(WaterTalkFiles.class, true);
Iterator iter = e.iterator();
String returns = "";
WaterTalkFiles file = (WaterTalkFiles)iter.next();
Blob blob = file.getData();
byte[] buffer = blob.getBytes();
String s = new String(buffer);
out.println(s);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != pm)
pm.close();
}
Now in client side when user click show button i want to show the file content in browser, not to download it.
My client side code is:
showfilecontentButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
String link = "/FileUploadByWaterTalks";
container.add(new HTML("ShowFile"));
}
});
The code above (Client side code) not showing content of file its just downloading the file.
But I don't want user to download it, I want show them the content of it.
And, do I have to configure something over here to work it out.
resp.setContentType("text/plain");
resp.setHeader("Content-Disposition", "attachment; filename=output.txt");
Hope you got what my problem is. Please be free to share your thoughts and solutions to achieve this.
Thanks.
UPDATED
Up on the bases of first answer here, I changed some portion of my code:
updated code sections are:
resp.setHeader("Pragma", "no-cache");
final String url = "http://127.0.0.1:8888/FileUploadByWaterTalks";
String name = "output.txt";
Anchor link1 = new Anchor(name);
RootPanel.get().add(link1);
link1.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Frame f = new Frame(url);
f.setSize("600px", "400px");
f.getElement().getStyle().setBorderWidth(0, Unit.PX);
RootPanel.get().add(f);
}
});
But still the browser asking me to save the file instead of showing it in the browser itself.
First remove the 'Content-Disposition' in your servlet.
Second, use a GWT Anchor in your code and when the user clicks open the link in a new window or an iframe.
Here you have a example using new window, and another using iframe:
final String url = "http://gwtquery.googlecode.com/git/README.txt";
String name = "README.txt";
Anchor link1 = new Anchor(name);
RootPanel.get().add(link1);
link1.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Window.open(url, "_blank", "");
}
});
Anchor link2 = new Anchor(name);
RootPanel.get().add(link2);
link2.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Frame f = new Frame(url);
f.setSize("600px", "400px");
f.getElement().getStyle().setBorderWidth(0, Unit.PX);
RootPanel.get().add(f);
}
});
This approach works for any file which the browser is capable to display, but be sure that you send the appropriate Content-Type header (text/plain, text/html, image/png etc.)
I am new to GWT and am trying to implement a file upload functionality.
Found some implementation help over the internet and used that as reference.
But have some questions related to that:
The actual upload or writing the contents of file on server(or disk) will be done by a servlet.
Is it necessary that this servlet (say MyFileUploadServlet) extends HttpServlet? OR
I can use RemoteServiceServlet or implement any other interface? If yes, which method do I need to implement/override?
In my servlet, after everything is done, I need to return back the response back to the client.
I think form.addSubmitCompleteHandler() can be used to achieve that. From servlet, I could return text/html (or String type object) and then use SubmitCompleteEvent.getResults() to get the result.
Question is that can I use my custom object instead of String (lets say MyFileUploadResult), populate the results in it and then pass it back to client?
or can I get back JSON object?
Currently, after getting back the response and using SubmitCompleteEvent.getResults(), I am getting some HTML tags added to the actual response such as :
pre> Image upload successfully /pre> .
Is there a way to get rid of that?
Thanks a lot in advance!
Regards,
Ashish
To upload files, I have extended HttpServlet in the past. I used it together with Commons-FileUpload.
I made a general widget for form-based uploads. That was to accommodate uploads for different file types (plain text and Base64). If you just need to upload plain text files, you could combine the following two classes into one.
public class UploadFile extends Composite {
#UiField FormPanel uploadForm;
#UiField FileUpload fileUpload;
#UiField Button uploadButton;
interface Binder extends UiBinder<Widget, UploadFile> {}
public UploadFile() {
initWidget(GWT.<Binder> create(Binder.class).createAndBindUi(this));
fileUpload.setName("fileUpload");
uploadForm.setEncoding(FormPanel.ENCODING_MULTIPART);
uploadForm.setMethod(FormPanel.METHOD_POST);
uploadForm.addSubmitHandler(new SubmitHandler() {
#Override
public void onSubmit(SubmitEvent event) {
if ("".equals(fileUpload.getFilename())) {
Window.alert("No file selected");
event.cancel();
}
}
});
uploadButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
uploadForm.submit();
}
});
}
public HandlerRegistration addCompletedCallback(
final AsyncCallback<String> callback) {
return uploadForm.addSubmitCompleteHandler(new SubmitCompleteHandler() {
#Override
public void onSubmitComplete(SubmitCompleteEvent event) {
callback.onSuccess(event.getResults());
}
});
}
}
The UiBinder part is pretty straighforward.
<g:HTMLPanel>
<g:HorizontalPanel>
<g:FormPanel ui:field="uploadForm">
<g:FileUpload ui:field="fileUpload"></g:FileUpload>
</g:FormPanel>
<g:Button ui:field="uploadButton">Upload File</g:Button>
</g:HorizontalPanel>
</g:HTMLPanel>
Now you can extend this class for plain text files. Just make sure your web.xml serves the HttpServlet at /textupload.
public class UploadFileAsText extends UploadFile {
public UploadFileAsText() {
uploadForm.setAction(GWT.getModuleBaseURL() + "textupload");
}
}
The servlet for plain text files goes on the server side. It returns the contents of the uploaded file to the client. Make sure to install the jar for FileUpload from Apache Commons somewhere on your classpath.
public class TextFileUploadServiceImpl extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
if (! ServletFileUpload.isMultipartContent(request)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
"Not a multipart request");
return;
}
ServletFileUpload upload = new ServletFileUpload(); // from Commons
try {
FileItemIterator iter = upload.getItemIterator(request);
if (iter.hasNext()) {
FileItemStream fileItem = iter.next();
// String name = fileItem.getFieldName(); // file name, if you need it
ServletOutputStream out = response.getOutputStream();
response.setBufferSize(32768);
int bufSize = response.getBufferSize();
byte[] buffer = new byte[bufSize];
InputStream in = fileItem.openStream();
BufferedInputStream bis = new BufferedInputStream(in, bufSize);
long length = 0;
int bytes;
while ((bytes = bis.read(buffer, 0, bufSize)) >= 0) {
out.write(buffer, 0, bytes);
length += bytes;
}
response.setContentType("text/html");
response.setContentLength(
(length > 0 && length <= Integer.MAX_VALUE) ? (int) length : 0);
bis.close();
in.close();
out.flush();
out.close();
}
} catch(Exception caught) {
throw new RuntimeException(caught);
}
}
}
I cannot recall how I got around the <pre></pre> tag problem. You may have to filter the tags on the client. The topic is also addressed here.
I am calling servlet from the gwt client program and setting
final FormPanel form = new FormPanel();
form.setMethod(FormPanel.METHOD_POST);
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setAction(GWT.getModuleBaseURL()+"/uploadservlet2");
Now on submit complete I want to retrieve a parameter from the servlet in this event,
form.addFormHandler(new FormHandler() {
public void onSubmit(FormSubmitEvent event) {
// This event is fired just before the form is submitted. We can take
// this opportunity to perform validation.
RootPanel.get().add(new Label("On submit"));
}
public void onSubmitComplete(FormSubmitCompleteEvent event) {
**///I want parameter here**
RootPanel.get().add(new Label("On submiting complete"));
}
});
Please tell me how I can do it.
in your onSubmitComplete:
public void onSubmitComplete(FormSubmitCompleteEvent event) {
String serverResponse = event.getResults();
}
you can let the server return HTML and put this in an HTML widget, or let the server return som JSON and parse this in GWT.