I have an html template file, lets call it index.tpl, which I want to process with a java servlet.
This is what index.tpl looks like:
<html>
<body>
<h1> Pet profile - {pet.name} </h1>
<p> age {pet.age} </p>
etc.
</body>
</html>
How can I make a servlet that takes this html as an input, processes it, and sends it back to the browser?
The user journey is basically:
1.User types something like webAppDomain.com/index.tpl?id=1
2.Servlet processes index.tpl and shows the filled template to the user
I'm specifically interested in knowing how the servlet can take the html code as an input to process.
I've tried searching for some way to do this, but I've literally just picked up servlets and I'm a bit lost.
In your servlet code for the servlet at "/", in the doGet() method read the path to find your template file:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String pathFromUrl = request.getPathInfo();
String filePath = BASE_PATH + "/" + pathFromUrl;
byte[] bytes = Files.readAllBytes(Paths.get(filePath));
String fileContent = new String (bytes);
String id = request.getParameterByName("id");
Pet pet = // get pet with id
// TODO modify fileContent with pet content
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().write(fileContent);
response.getWriter().flush();
}
you can try this by using Velocity
add Velocity dependency
put this in your index.tpl
String templateFile = "index.tpl";
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
Template template = velocityEngine.getTemplate(templateFile);
VelocityContext context = new VelocityContext();
context.put("pet.name", "Fluffy");
context.put("pet.age", 5);
StringWriter writer = new StringWriter();
template.merge(context, writer);
String result = writer.toString();
set content for response
response.setContentType("text/html");
response.getWriter().write(result);
Related
I am trying to use jsp and java to display information read from a csv to a website. I'm using Tomcat v9.0 with Eclipse.
The java code works as expected when running it just in java—it reads the csv data into an ArrayList of Song objects. However, when running the jsp file, it throws a filenotfoundexception.
The original java code reads and parses the csv in the getter function of "ReadBillboardCSV" here:
public ArrayList<BillboardSong> getReadBillboardCSV() throws FileNotFoundException {
Reader in = new FileReader("testFile.csv");
ArrayList<BillboardSong> readSongs = new ArrayList<BillboardSong>();
try {
Iterable<CSVRecord> records = CSVFormat.RFC4180.parse(in);
for (CSVRecord record : records) {
BillboardSong newSong = new BillboardSong();
readSongs.add(newSong);
newSong.setPosition(Integer.parseInt(record.get(0)));
My servlet calls the getter, then sets the attribute.
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession ses = request.getSession(true);
ReadBillboardCSV readData = new ReadBillboardCSV();
ArrayList<BillboardSong> songsArray = readData.getReadBillboardCSV();
ses.setAttribute("billboardArray", songsArray);
}
Here is the main portion of the jsp:
<%
RequestDispatcher rd = request.getRequestDispatcher("/ServletOne");
rd.forward(request, response);
%>
Is there a reason it cannot read the file when I run it on Tomcat?
I have created a login page using HTML page and Java Servlet class. However I am wondering if it is possible to have a JSP instead of the Java file? So essential use this code in the Java class into a JSP page and still have the same functionality?
<form action="Lognn" method="post">
<input type="text" name="name"/>
<input type="text"name="pass"/>
Java class
Public class Login extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
String name = request.getParameter("name");
String pass = request.getParameter("pass");
MyDb1 db = new MyDb1();
Connection con = db.getCon();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select uid,name,pass from register where email = '"+name+"' and pass = '"+pass+"'");
while ((rs.next())) {
String uid = rs.getString("uid");
//out.println("User id"+uid);
HttpSession session=request.getSession();
session.setAttribute("name",uid);
response.sendRedirect("http://localhost:8080/Final/userprofile.jsp");
}
} catch (SQLException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
Generally, each JSP is translated and compiled to a servlet, and a lot of things you can do with servlets you can do with JSP.
You can change your form action="Lognn" method="post" to form action="Lognn.jsp" method="post", then
in Lognn.jsp you can read your input parameters from html like <%= request.getParameter("name")%>, then
in Lognn.jsp you can connect to a database directly or you can use EJB
and finally you can give html output back from the same JSP.
It formally will work without servlet, but in CATALINA_HOME/WORk directory a servlet will be internally created and compiled from your JSP.
Idea: I have a Spring web MVC action that should accomplish one or both of these taks:
Download a file from a remote server and write the input stream to the response output stream
Or catch the exception of the download, set one of multiple error messages and redirect to the /addresses page. The address page will display the error
Problem: Spring is unable to download a file and redirect in case of a problem - somehow flash attributes don't work because the get lost in the redirect:
#ResponseBody
#RequestMapping(value = "/download/{fileaddress}", method = RequestMethod.GET)
public void download(HttpServletRequest request, HttpServletResponse response, #PathVariable(value = "fileaddress") String fileaddress) throws Exception
{
if(fileaddress != null && fileaddress.length() > 0)
{
try
{
// Get the remove file based on the fileaddress
RemoteFile remotefile = new RemoteFile(fileaddress);
// Set the input stream
InputStream inputstream = remotefile.getInputStream();
// Write the input stream to the output stream or throw an exception
Utils.writeTo(inputstream, response.getOutputStream());
}
catch(MyExceptionA)
{
// TODO: Define error message a and pass it to /addresses
// PROBLEM: Flash attributes that contain all critical error information don't work
response.sendRedirect(request.getContextPath() + "/addresses");
}
catch(MyExceptionB)
{
// TODO: Add another error message and redirect
response.sendRedirect(request.getContextPath() + "/addresses");
}
catch(MyExceptionC)
{
// TODO: Add another error message and redirect
response.sendRedirect(request.getContextPath() + "/addresses");
}
catch(MyExceptionN)
{
// TODO: Add another error message and redirect
response.sendRedirect(request.getContextPath() + "/addresses");
}
}
else
{
// TODO: Add error message
response.sendRedirect(request.getContextPath() + "/addresses");
}
}
JSP page of /addresses:
<%# page pageEncoding="UTF-8" %>
<%# taglib prefix="tags" tagdir="/WEB-INF/tags" %>
<%# taglib prefix="core" uri="http://java.sun.com/jsp/jstl/core" %>
<tags:index>
<jsp:attribute name="content">
<core:if test="${not empty error}">
<div class="alert alert-danger">
<p>${error}</p>
</div>
</core:if>
<p>Page under construction!</p>
</jsp:attribute>
</tags:index>
Question: How I am able to display the error message (Simple string for example) in the /addresses site? Working with different URL parameter (error=errora, error=errorb ...) is a huge pain, if there are multiple error types and passing the error message as GET parameter looks unprofessional and is the root of encoding problems.
What you need is the RedirectAttributes a specialization of the Model which controllers can use to select attributes for a redirect scenario.
So for a working example see below code:
#ResponseBody
#RequestMapping(value = "/download/{fileaddress}", method = RequestMethod.GET)
public Object download(#PathVariable(value = "fileaddress") String fileaddress, RedirectAttributes redirectAttrs) throws Exception {
if(StringUtils.hasText(fileaddress)){
try{
// Get the remove file based on the fileaddress
RemoteFile remotefile = new RemoteFile(fileaddress);
// Set the input stream
InputStream inputstream = remotefile.getInputStream();
// asume that it was a PDF file
HttpHeaders responseHeaders = new HttpHeaders();
InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
responseHeaders.setContentLength(contentLengthOfStream);
responseHeaders.setContentType(MediaType.valueOf("application/pdf"));
return new ResponseEntity<InputStreamResource> (inputStreamResource,
responseHeaders,
HttpStatus.OK);
} catch (MyExceptionA | MyExceptionB | MyExceptionC | MyExceptionD ex) {
redirectAttrs.addFlashAttribute("error", ex.getMessage());
}
} else {
redirectAttrs.addFlashAttribute("error", "File name is required");
}
return "redirect:/addresses";
}
Update: I've thought the question is about situations where RedirectAttributes are not available because otherwise, the solution is pretty obvious (use RedirectAttributes).
Orignal answer:
I'm using the following code to bind messages to the flash map in situations where Spring doesn't support RedirectAttributes (e.g. in ExceptionHandler methods):
public static Feedback getInstance(HttpServletRequest request, HttpServletResponse response) throws IllegalArgumentException {
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
Object o = flashMap.get(KEY);
if (o != null) {
if (o instanceof Feedback) {
return Feedback.class.cast(o);
} else {
throw new IllegalArgumentException(...);
}
} else {
FeedbackContainer feedbackContainer = new FeedbackContainer();
flashMap.put(KEY, feedbackContainer);
FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
flashMapManager.saveOutputFlashMap(flashMap, request, response);
return feedbackContainer;
}
where Feedback / FeedbackContainer is a container for messages which is then accessed in JPSs via JSON serialization. In your case you may use a mere String with key "error" and access it directly in the JSP:
void storeErrorMsg(HttpServletRequest request, HttpServletResponse response, String message) {
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
flashMap.put("error", message);
FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
flashMapManager.saveOutputFlashMap(flashMap, request, response);
}
The main reason for using my own message container is the possibility to have multiple messages with different levels and additional getInstance methods for RedirectAttributes, Model or ModelMap, so I don't have to care about duplicate feedback bindings and/or the different binding code.
i can't explain about why it is not downloading a file from server but coming to your second query , you can redirect in two ways either take your method return type as ModelAndView and do like this
ModelAndView mav = new ModelAndView("write here your jsp page name even is will work for remote server");
try {
mav.addObject("some key","here you can write any message that will you can show in your jsp page..");
then return mav.
like this you can redirect how many pages you want with if condition.
and second approach you can take your method return type String and you can directly redirect to your required jsp.
I would suggest the following approach:
Since you have some remote file as an input stream you cannot read it from the point where an exception occurred. Hence you can decrease error chances with first downloading the file to a temp folder on local host.
Here if there is an error, you can either redirect as you suggested, or just make another attempt and redirect after several failed attempts. This way you are not writing anything to the stream until you are sure the file downloaded successfully.
Once the file is downloaded to the server you can pass it to the client. For instance you can read bytes and save current position. Suppose there is an exception in the middle of writing to the stream. You can restore writing from failed point reading from the middle.
A small example
...
final String localFileName = saveFileLocally(fileaddress)
if (localFileName == null) {
response.sendRedirect(request.getContextPath() + "/addresses");
} else {
safeWrite(new BufferedInputStream(new FileInputStream(new File(localFileName))), response.getOutputStream());
}
...
safeWrite should support local file read exception handling with reading from the file middle. There should be standard java api for such operations.
I am to send a picture from an android phone to a local web server on my computer. I'd like to save the picture to a folder on the local server. My plan is to write some kind of controller that takes care of the received picture and saves it. So basically I think I need to create a controller that takes in a parameter (the picture) and saves it to a folder at the server. I have been searching all over and haven't yet found what I'm looking for.
Therefore what I'd like to know is:
How is such a controller written.
I am currently using Apache Tomcat/7.0.39 web server, Spring MVC Framework through STS and my OS is Windows 7.
Aprreciate any help I can get! Code examples would be greatly appreciated.
Thank you,
Mat
Apache Commons FileUpload is pretty easy to use to process multipart form posts. I don't think I've used it with Spring MVC, but there are examples out there.
For a similar function (loading photos from Android to servlet), here's the Android client code I use (edited slightly for posting here):
URI uri = URI.create(// path to file);
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.STRICT);
// several key-value pairs to describe the data, one should be filename
entity.addPart("key", new StringBody("value"));
File inputFile = new File(photoUri.getPath());
// optionally reduces the size of the photo (you can replace with FileInputStream)
InputStream photoInput = getSizedPhotoInputStream(photoUri);
entity.addPart("CONTENT", new InputStreamBody(photoInput, inputFile.getName()));
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(uri);
HttpContext localContext = new BasicHttpContext();
httppost.setEntity(entity);
HttpResponse response = httpclient.execute(httppost, localContext);
and here's the code to receive it. First, be sure to tag your servlet class as supporting multipart messages:
#MultipartConfig
public class PhotosServlet extends HttpServlet
and then the relevant part of the body:
HttpEntity entity = new InputStreamEntity(request.getPart("CONTENT").getInputStream(), contentLength);
InputStream inputFile = entity.getContent();
// string extension comes from one of the key-value pairs
String extension = request.getParameter(//filename key);
// first write file to a file
File images = new File(getServletContext().getRealPath("images"));
File filePath = File.createTempFile("user", extension, images);
writeInputDataToOutputFile(inputFile, filePath); // just copy input stream to output stream
String path = filePath.getPath();
logger.debug("Wrote new file, filename: " + path);
Hope it helps.
This is the solution I went with using STS with MVC Framework template:
The controller:
#Controller
public class HomeController {#RequestMapping(value = "/upload", method = RequestMethod.POST)
public String handleFormUpload(#RequestParam("name") String name, #RequestParam("file") MultipartFile file) throws IOException {
if (!file.isEmpty()) {
byte[] bytes = file.getBytes();
FileOutputStream fos = new FileOutputStream(
"C:\\Users\\Mat\\Desktop\\image.bmp");
try {
fos.write(bytes);
} finally {
fos.close();
}
return "works";
} else {
return "doesn't work";
}
}
}
The .jsp file (the form):
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# page session="false" %>
<html>
<head>
<title>Upload a file please</title>
</head>
<body>
<h1>Please upload a file</h1>
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit"/>
</form>
</body>
I'm trying to display a PDF report on a webApp, I've been following this tutorial here
and it creates the pdf file fine, but I'm having trouble trying to display it in the browser. In my xhtml I have a button, once that button is clicked, a function calling the servlet is called. it goes into the servlet and created a pdf document fine. but I can't seem to figure out how to display it on the screen. is there a way to show the document on a new browser window, or new tab? or even the same one.
I'm working with Java Server faces 2.0 in Eclipse. and have a Tomcat 7.0 server.
on my webxml I added the following code specified in the example:
<servlet>
<servlet-name>PdfServlet</servlet-name>
<servlet-class>com.bravo.servlets.PdfServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PdfServlet</servlet-name>
<url-pattern>/PdfServlet</url-pattern>
</servlet-mapping>
and my servlet looks like this ( pretty much the same as the example):
#WebServlet("/PdfServlet")
public class PdfServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Font font = new Font(Font.FontFamily.TIMES_ROMAN, 12,
Font.NORMAL, BaseColor.RED);
/**
* Default constructor.
*/
public PdfServlet() {
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
invokePDFViewer(response);
Document document = new Document();
try{
PdfWriter.getInstance(document, response.getOutputStream());
document.open();
addContent(document);
document.close();
}catch(DocumentException e){
e.printStackTrace();
}
}
private void invokePDFViewer(HttpServletResponse response){
response.setContentType("application/pdf");
}
private void addContent(Document document)throws DocumentException {
PdfPTable table = new PdfPTable(2);
Paragraph paragraph = new Paragraph ("Este es un parrafo en celda 1", font);
table.addCell(paragraph);
table.addCell("2");
table.addCell("3");
table.addCell("4");
table.addCell("5");
table.addCell("6");
document.add(table);
}
}
the xhtml I'm calling the servlet from looks like this:
....
function callPdfServlet(){
$.ajax({
type: 'POST',
cache: 'false',
data: 'codeType=notUsed',
url: '/miloWeb/PdfServlet',
async: false,
success: function(data){
},
error: function (xhr, ajaxOptions, thrownError){
alert(ajaxOptions);
}
});
}
.....
<h:commandButton id="reportButton" action=" " styleClass="button" value="get Report" onclick="callPdfServlet();"></h:commandButton>
So at the end, all it does right now is I go into the xhtml in my browser, click on the button, and it hits the servlet, goes through the code, and then thats it. my browser just reloads the screen and nothing else happens. so i need to show the pdf I just created. Thanks in advance for your help!
//************************************************************************************
EDIT 01/02/12:
after reading this and this
I can see that the action in the commandButton will take me to the "response".xhtml with "response" being a string that I either hardcode in, or is returned by an action in a Managed Bean. that response ( if not put in my faces-config file ) will take me to the page IF it's in the same folder as my current page.
so I believe that when I put "miloWeb/PdfServlet" as a response for the action, It looks for the page in the same folder ( which it's not) and since it doesn't find anything just reloads the page. And since I have a break point In the servlet, I am 100% sure it's not hitting it.
so my question is: How do I redirect my page to miloWeb/PdfServlet??
to clarify, it works fine if I put the name of another xhtml in the same folder. so it is working that way.
//This is what I tried just for reference:
Instead of going through the ajax call I've changed the button to
<h:commandButton id="reportButton" action="/miloWeb/PdfServlet" styleClass="button" value="get Report"></h:commandButton>
but it Just reloads the page and doesn't take me to the Servlet.
so another thing I tried was tried to go thought the action of the button calling a Managed Bean:
public String actionPdf(){
return "/miloWeb/PdfServlet";
}
again,same thing, the function returns the string, but it still doesn't take me to the servlet.
Just post a regular form rather than posting in AJAX, and the browser will load the response from your PDF servlet in the page rather than loading it from JavaScript and ignoring it completely:
<form method="post" action="/miloWeb/PdfServlet">
<input type="hidden" name="codeTyped" value="notUsed"/>
<input type="submit" value="Show PDF"/>
</form>
in the action of the commandButton, I had to type this in:
public String doThis(){
String url = "url of your servlet";
FacesContext context = FacesContext.getCurrentInstance();
try {
context.getExternalContext().dispatch(url);
}catch (Exception e) {
e.printStackTrace();
}
finally{
context.responseComplete();
return "";
}
So with this, I get the context root and redirect it there. url being /PdfServlet