Can't display text after displaying image in servlet? - servlets

I wrote a servlet which takes the name of a image from the client and displays it to client by converting it to byte array.after displaying the image now when i am trying to print some text i m not able to do so.it simply doesn't print the text even after using PrintWriter.
I am using jboss application server to deploy it.
here is the servlet-Image.java:
package javaserv.image;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.ImageIcon;
public class Image extends HttpServlet {
private static final long serialVersionUID = 1L;
public Image()
{
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String imagename = request.getParameter("imagename");
File fileimage = new File("C:/langs/projects/javaserv/"+imagename+".jpg");
byte [] imagearray;
imagearray = new byte[(int)fileimage.length ()];
FileInputStream fis = new FileInputStream (fileimage);
fis.read (imagearray);
response.setContentType("image/jpeg");
response.setContentLength((int)fileimage.length ());
ServletOutputStream out = response.getOutputStream();
int i=0;
while(i<imagearray.length)
{
out.write(imagearray[i]);
++i;
}
out.flush();
out.close();
out = response.getOutputStream();
response.setContentType("text/html");
out.println("<html><body>");
out.println("here is your image");
out.println("<p>");
out.println("</html></body>");
out.close();
}
}
"imagename" is the name of the image entered by client

You can either write your JPEG to the out, or the HTML, not both.
Your code writes the JPEG to the output, closes the output stream, then tries to open it again to write some HTML.
If you want to display a synamic image on a HTML page, you should be using a servlet for the image, and a JSP page for the HTML.

You basically need to let the client fire two HTTP requests. One to the HTML which in turn contains an <img> element which let the webbrowser automagically send another HTTP request to the image file.
First create a HTML page like follows:
<!DOCTYPE html>
<html lang="en">
<head>
<title>An image</title>
</head>
<body>
<p>Here is your image</p>
<p><img src="images?imagename=foo.gif"></p>
</body>
</html>
Where I assume that your image servlet is listening on an url-pattern of /images. Finally just give the enduser the URL to the HTML page (can also be a JSP page by the way) instead of the URL to the image. The enduser will then retrieve a HTML page with some text and an image.
That said, your imageservlet is honestly said pretty poor written in terms of speed, memory efficiency and resource handling. I'd suggest to have a look for this basic example how to do it properly.

You can inline the image, then the browser only does one request.
<img src="data:image/png;base64,....

Related

Vaadin 14 - Show errors at file upload like at any other input field

Brief question first:
How can I show an upload error message in the same style of all the other input fields?
Details:
Vaadin 14.1.5 offers an upload-element: https://vaadin.com/components/vaadin-upload/java-examples
I created an upload field with this code:
MemoryBuffer buffer = new MemoryBuffer();
Upload upload = new Upload(buffer);
A failure message for too large file size is enforce by this line:
upload.setMaxFileSize(1);
Translation is done with UploadI18N (see https://vaadin.com/api/platform/14.1.5/com/vaadin/flow/component/upload/UploadI18N.html ):
upload.setI18n(buildMyUploadI18N(Locale.GERMAN));
And with all the listeners I can receive and show error messages at server-side, e.g. for rejection:
upload.addFileRejectedListener(new ComponentEventListener<FileRejectedEvent>() {
#Override
public void onComponentEvent(FileRejectedEvent event) {
Notification.show(event.getErrorMessage());
}
});
This code works fine and the system shows a notification message to the user when the file to upload is too large.
But: this validation-message-behavior differs from what the user is used to: Red text next to the input field (see screenshot).
How can I show an upload error message in the same style of all the other input fields?
Another option is to use a Paragraph, as in the example page you have linked. The source code for it could be found here: addRejectedListener
So once rejected listener is called, add a paragraph with a red text and possibly set background of upload to pink(or any other color/style you would like it to have). Below is a simplified version of the approach (You should put styles to a separate css file and set/remove a class to upload)
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.HtmlComponent;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.upload.Upload;
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
import com.vaadin.flow.router.Route;
#Route("multiuploadView")
public class MultiFileUploadView extends VerticalLayout {
Div output = new Div();
Upload upload;
public MultiFileUploadView(){
MemoryBuffer buffer = new MemoryBuffer();
upload = new Upload(buffer);
upload.setMaxFiles(1);
upload.setDropLabel(new Label("Upload a 300 bytes file in .csv format"));
upload.setAcceptedFileTypes("text/csv");
upload.setMaxFileSize(300);
upload.addFileRejectedListener(event -> {
Paragraph component = new Paragraph();
showOutput(event.getErrorMessage(), component, output);
});
add(upload,output);
}
private void showOutput(String text, Component content,
HasComponents outputContainer) {
outputContainer.removeAll();
HtmlComponent p = new HtmlComponent(Tag.P);
p.getElement().setText(text);
p.getElement().getStyle().set("color","red");
upload.getElement().getStyle().set("background","pink");
outputContainer.add(p);
outputContainer.add(content);
}
}
And this looks like this:
But, otherwise, I would say that your workaround is pretty much what one can do :)
My current workaround is as follows:
The system creates a disabled Textfield in addition to the Upload-element
TextField filenameField = new TextField();
filenameField.setEnabled(false);
Every error listener at the Upload-element then sets the error message at the TextField:
upload.addFileRejectedListener(new ComponentEventListener<FileRejectedEvent>() {
#Override
public void onComponentEvent(FileRejectedEvent event) {
filenameField.setInvalid(true);
filenameField.setErrorMessage(event.getErrorMessage());
}
});
and
upload.addFailedListener(new ComponentEventListener<FailedEvent>() {
#Override
public void onComponentEvent(FailedEvent event) {
filenameField.setInvalid(true);
filenameField.setErrorMessage(event.getReason().getMessage());
}
});
and reset invalid-status and set new filename at success:
upload.addSucceededListener(event -> {
filenameField.setValue(StringUtils.trimToEmpty(event.getFileName()));
filenameField.setInvalid(false);
});
This is how it looks like - not my preferred solution (because the filename is not errorneous but the file size), but for the moment this is OK for me:

Spring Boot + Thymeleaf css is not applied to template

I am evaluating Thymeleaf and Flying Saucer for pdf generation from templates, and I am having a problem with applying css to my Thymeleaf template. I already read the relevant questions & answers here, here, and here; but none of the suggested solutions fixed my problem.
This is how my resources folder looks like:
So I am using the default directories that Spring will look for. And that's how the head tag looks like in my template.html:
<head>
<title>Spring Boot and Thymeleaf Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="../static/css/style.css" th:href="#{/css/style.css}"/>
</head>
If I inline my css in template.html then the generated pdf file will be styled properly (so there shouldn't be a problem with how I generate the pdf). However, when I try to link to the css file as shown above the generated pdf is not styled (so the css is not applied).
Lastly, I can access my css file at http://localhost:8080/css/style.css, so there doesn't seem to be a problem with Spring serving the static content.
For completeness, this is how I generate the pdf:
private final SpringTemplateEngine templateEngine;
private final Log log;
#Autowired
public PdfGenerator(SpringTemplateEngine templateEngine) {
this.templateEngine = templateEngine;
log = LogFactory.getLog(getClass());
}
public void generate(HttpServletRequest servletRequest, HttpServletResponse servletResponse, ServletContext servletContext) {
// Parse the pdf template with Thymeleaf
Locale locale = getLocale(servletRequest);
WebContext context = new WebContext(servletRequest, servletResponse, servletContext, locale);
context.setVariable("user", buildDummyUser());
context.setVariable("discounts", buildDummyDiscounts());
String html = templateEngine.process("template", context);
// Create the pdf with Flying Saucer
try (OutputStream outputStream = new FileOutputStream("generated.pdf")) {
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(html);
renderer.layout();
renderer.createPDF(outputStream);
} catch (IOException | DocumentException e) {
log.error("Error while generating pdf", e);
}
}
I am using WebContext instead of Context because I was getting the following error with Context:
org.thymeleaf.exceptions.TemplateProcessingException: Link base "/css/style.css" cannot be context relative (/...) unless the context used for executing the engine implements the org.thymeleaf.context.IWebContext interface
What am I missing here, why is my style.css not applied to template.html?
I had same problems and I was also trying to use thymeleaf template resolver for pdf generation. I did lots research on thymeleaf and spring framework, I tried WebContext, I tried HttpServletRequest, I tried some of Spring Thymeleaf integration solutions it was not working either. So I think it was not syntax error, and I finally end up with using absolute path instead of relative.
Url for reference
Here the reason with my assumption, lets say our resources are served on localhost:8080/myapp/css/style.css. And the relative path to request resource is really ups to what context it relatives to.
For eaxmple a normal thymeleaf model Veiw, which return as html pages on browser for client, so the context in that case would be the request hostname, port and application context(eg: localhost:8080/myapp). And relative path will be based on that. So if relative path is /css/style.css, context + relative path will result to be localhost:8080/myapp/css/style.css
Unlike web context, in our case, offline template is on server backend, so the context I assume would be the server running context, which would be the local server path + appcontext(eg: D:/myServer/apps/myapp), relative path /css/style.css on this would be D:/myServer/apps/myapp/css/style.css, this is not make sense. In order to use static resources, I have to pass it's absolute path.
I started use :
<link rel="stylesheet" type="text/css" th:href="#{http://localhost:8080/myapp/css/style.css}"/>
It's working fine but what if there are multiple host names or server is running on a proxy, then this is going to be a hard coded solution. It's better to know what is the real base url the user is requesting. So we can't really get rid off HttpSevletRequest.
Here is my code:
1.Config resource handler:
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**")
.addResourceLocations("classpath:/css/")
.setCachePeriod(31556926);
}
Get base url from HttpServletRequest, you can inject it in method or autowired in your service class, or get from RequestContextHolder. I write this in my Service class:
private static String getCurrentBaseUrl() {
ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest req = sra.getRequest();
return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath();
}
This is the place I use template engine in my class:
Context context = new Context();
context.setVariable("variales", variables);
context.setVariable("baseUrl", getCurrentBaseUrl());
String content = springTemplateEngine.process("myTemplate",context);
In my template, I use absolute css url like this:
<link type="stylesheet" th:src="#{|${baseUrl}/css/style.css|}" />
Syntax looks fine so the problem is not with the syntax.
Also you cannot use #{...} syntax without an IWebContext interface so You are getting this exception.
I had a similar problem - my css was not applied to my template page.
My problem was that the css file was in css sass format
.table
margin: 0 0 40px 0
when I convert it to the normal css format like
.table {
margin: 0 0 40px 0;
}
it worked
I solved this problem by changing the path structure in href. I had the same directory structure as you (html files are in templates doc, css files are in static doc).
<head>
<title>Spring Boot and Thymeleaf Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
</head>
It might help you to apply css to your html page.
I found a lazy man's way of taking care of this. It works, with a very simple approach. The 'inserted' fragment is just a CSS style tag in the body of a simple HTML document. I place this in the HEAD of my target file, right where I would have put the LINK REL tag:
<th:block th:insert="std-reports/std-reports-css-fragment.html :: style"></th:block>

display image from database on page load in servlet

I would like to show an image when the page loads in a servlet. Considering that this page is an html page, I don't really understand how the image to be displayed can be mentioned programatically(say, for example database.
Had it been a servlet, I would have just done something like the following which shows an image once the button is clicked. But how do I do the same for an html?
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("<HTML>");
out.print("<HEAD><TITLE>Upload Image</TITLE></HEAD>");
out.print("<BODY>");
out.print("<img src='images/imagethree.jpg' alt='image' />");
out.print("<img src='images/imageone.jpg' alt='image' />");
out.print("<input type=\"submit\" value=\"select\">");
out.print("</BODY>");
out.print("</HTML>");
out.close();
}
i am not sure but you can retrieve image from database at the time of init() or by using some super calling statements in doget() method like(super or this()) and after that you can assign the image.
Assume that your folder structure is something like this:
|_ Web Contents
|_ images
| |_ a.png
|_ WEB-INF
And your Context Path is SampleWebApp. following image tag will show the picture:
<img src="/SampleWebApp/images/a.png">

HTMLUnit cannot find any element after clicking "OK" on an iFrame after Login

I appreceate any little help I can get on the issue I'm facing with HtmlUnit.
What I need to do is to login to my application, go to the home page and get a list of all links, text fields, buttons, etc., on my home page.
I tried coding this, and here's what I can do.
I can launch the page, find the login controls, enter user id and password and click Login.
The login is successful. At this point, my application displays the home page, which is masked by an iFrame on top, which displays the last login time and other details. There's an OK button on that which I have to click for the underlying home page to be unmasked.
I am able to click the OK button as well.
And now here's what I am unable to do.
Once I click OK, the underlying home page is unmasked, yet my HtmlPage object is empty (not null).
Below is my code.
import java.io.IOException;
import java.net.MalformedURLException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
public class HTMLUnitSample {
public static void main(String args[]){
final WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getCookieManager().setCookiesEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setPopupBlockerEnabled(false);
try{
//Get the first page
final HtmlPage loginPage = webClient.getPage("http://****:****/****/****");
//Fill up the login form
loginPage.getElementById("USERID").setAttribute("value", "****");
loginPage.getElementById("user_pwd").setAttribute("value","****");
final HtmlForm loginForm = loginPage.getFormByName("frmLogin");
HtmlSubmitInput button = loginForm.getInputByName("submit");
HtmlPage homePage = button.click();
/*
System.out.println("Body - " + homePage.getBody().asText());
System.out.println("No. of Frames in Home Page - " + Inte ger.toString(homePage.getFrames().size()));
System.out.println("Total no. of elements on Home Page - " + Integer.toString(homePage.getElementsByTagName("*").size()));*/
//Click the OK button
HtmlButtonInput okButton = (HtmlButtonInput)homePage.getElementByName("Ok");
HtmlPage homePage2 = okButton.click();
System.out.println(homePage2.asText());
System.out.println("Done");
}
catch(MalformedURLException e){
e.printStackTrace();
}
catch(IOException e){
e.printStackTrace();
}
}
}
The output I get for
System.out.println(homePage2.asText());
is simply an empty string.
I even tried
homePage2.getElementsByTagName("*");
but in vain.
What I need is to actually find the elements on the home page after I click OK.
Please help me. Any little help is greatly appreciated.

Flash TextField HTML - How do I prevent the error dialogue for missing images? (Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found)

I'm using a Flash TextField control to display some HTML content inside a Flash presentation to be shown on a large touch-screen kiosk. Unfortunately, if any image tag in the displayed HTML content points to a non-existent image, a dialogue is shown with the error message
Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.
I am trying to avoid having that dialogue pop up. The solution for loading content through a loader class is to catch IOErrorEvent.IO_ERROR, but I've tried listening for that on the TextField, on stage, Main and loaderInfo to no avail. I've tried wrapping the whole thing in a try-catch, and that also doesn't work.
Here's the simplified code I'm using to find solutions:
package {
import flash.display.Sprite;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.text.TextField;
import flash.text.TextFieldType;
public class Main extends Sprite {
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var html:TextField = new TextField();
html.type = TextFieldType.DYNAMIC;
html.multiline = true;
html.htmlText = "Bogus image: <img src=\"foo.jpg\" />";
addChild(html);
}
}
}
Edit: And here's the entire working code.
For dynamic content and so forth, of course, you would need a list of images and a function to generate handlers, etc.
package {
import flash.display.Loader;
import flash.display.Sprite;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.text.TextField;
import flash.text.TextFieldType;
public class Main extends Sprite {
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var html:TextField = new TextField();
html.type = TextFieldType.DYNAMIC;
html.multiline = true;
html.htmlText = "Bogus image: <img id=\"image\" src=\"foo.jpg\" />";
var loader:Loader = html.getImageReference("image") as Loader;
if(loader){
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event):void {
trace("Error loading foo.jpg!");
});
}
addChild(html);
}
}
}
You can add ID's to images
html.htmlText = "Bogus image: <img src=\"foo.jpg\" id="image" />";
And then setup IOErrorEvent handler to each image in HTML
var loader:Loader = html.getImageReference("image") as Loader;
if(loader){
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event):void{});
}
This is a cool problem.
I have two suggestions.
1) Don't use TextField. I'm guessing that you developed in Flash before Flex, like me. You may already know this, but it took me awhile to find out: The TextField object isn't meant to be used for regular use in Flex. Check this out from the Flex3 language ref:
The TextField class is used to create
display objects for text display and
input. All dynamic and input text
fields in a SWF file are instances of
the TextField class. You can use the
TextField class to perform low-level
text rendering. However, in Flex, you
typically use the Label, Text,
TextArea, and TextInput controls to
process text.
Obviously, there's nothing wrong with using TextField, but I've found that when I'm trying to figure out tricky problems, it's really helpful to do as much 'by the book' as I can to remove unknowns (as much as possible, at least).
2) I think I'd try either extending the Text component, or else creating a new component based on Text. In this component I'd add logic to load and insert images into the TextField object. That way, you could easily build and validate the string to insert into the TextField object prior to inserting it into the TextField.
If you get this working, please post - I could use it myself. :)
If there's a way for you to use the new FTE/TLF components, do so. Adobe is basically turning its back on the old TextField API, and this same error is a reason that I had to abandon many projects and components in the past. This error is thrown and basically cannot be caught. One of the worst aspects of Flash work in my opinion.
TLF addresses these problems and is SO much easier to work with. What would take days of experimentation in the old API now takes only a few hours. I've built a few rich text editors on the new API and it is SO very nice to use. You'll be glad you did :)
I was able to detect when an image has loaded, but I think I'll follow the TLF advice. anyways if you need to know, you have to implement an enter_frame event listener on the Loader and check for the contentInfo on the bytes property the Lenght, if the image hasn't load the length is 0xffffffff, if the image has loaded the length is the size of the file, and if there is an error the bytes properties es NULL.
var html:TextField = new TextField();
html.width=388.95;
html.height=400;
html.type = TextFieldType.DYNAMIC;
html.multiline = true;
html.htmlText = "Bogus image: <img id='image' src='foo.jpg'/>";
var loader:Loader = html.getImageReference("image") as Loader;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHan);
function completeHan(e:Event){
addChild(html);
}
This will work..
This is a problem I'm also dealing with: it's a real annoyance. I'd really like to be able to catch all the errors. I assumed you could say...
stage.addEventListener(IOError.IO_ERROR, myErrorHandler);
...but that doesn't seem to work, as you've pointed out.
Perhaps you can check to make sure the kiosk's flash player isn't the debug version. I don't think that the release version throws the dialogs (could be wrong).
Impossible! Same problem if you use the Loader to load images that doesnt exists! Flex is a framework and the Image class uses this flash Loader object but with plenty of lines of code (check out the source of SwfLoader...).
You can check your image URL before set the htmlText property or you can create your own component to display Text and Images..
I can't believe this simple & stupid bug is not still fixed by Adobe!

Resources