blob image render in spring mvc 3.0 - spring

I am trying to read blob type image which is coming from Database. My method in controller. Only Image file is displaying on JSP nothing else
#RequestMapping(value = "/showDetails")
public ModelAndView showDetails(#RequestParam("doc") int id,
HttpServletResponse responce) {
ModelAndView mView = new ModelAndView();
File file = documentDao.getFileDetail(id);
byte[] bytes = null;
try {
OutputStream op = responce.getOutputStream();
int length = (int) file.getContent().length();
bytes = file.getContent().getBytes(1, length);
op.write(bytes);
op.flush();
op.close();
responce.setContentType("image/gif");
mView.addObject("image", op);
} catch (Exception e1) {
e1.printStackTrace();
}
mView.addObject("file", file);
mView.setViewName("filedetails");
return mView;
}
The above method in my controller class. And I want to render image as well as some text on JSP. But only image is coming in Browser.

You can't do it this way in Spring (in Servlets more precisely). Create two different controllers -- one will serve image and another will return JSP page with text. To get image at page just properly set value of src attribute of img tag: it should point to first controller.

Related

Downloading a pdf file from JSP file in Java

I want to download one of my JSP pages as PDF. For example, this is my function which returns to JSP page:
#RequestMapping(value = "/cart", method = RequestMethod.GET)
public String cart(HttpSession httpSession ,final Model model, RedirectAttributes redirectAttributes){
StudentData studentData =(StudentData)httpSession.getAttribute("student");
if(studentData ==null){
redirectAttributes.addFlashAttribute("isFromCartFlag", Boolean.TRUE);
return REDIRECT_PREFIX + "/login" ;
}
final List<ProductData> cartDataFromDb = listofProducts.retrieveCartEntriesFromDb(studentData.getName());
List<ProductData> sessionCart = (List<ProductData>) httpSession.getAttribute("sessionCart");
if (sessionCart != null) {
for (ProductData sessionCartEntryData : sessionCart) {
for (ProductData cartEntryData : cartDataFromDb) {
if(cartEntryData.getProductName().equalsIgnoreCase(sessionCartEntryData.getProductName())){
int quantityOfItem = cartEntryData.getQuantity()+sessionCartEntryData.getQuantity();
sessionCartEntryData.setQuantity(quantityOfItem);
}
}
listofProducts.insertCartEntriesIntoDb(studentData.getName(),sessionCartEntryData.getProductName(),sessionCartEntryData.getQuantity());
}
}
final List<ProductData> cartData = listofProducts.retrieveCartEntriesFromDb(studentData.getName());
List<ProductData> productDataListForCart = new ArrayList<ProductData>();
for (ProductData cartDataEntry : cartData) {
ProductData productData = listofProducts.displayProductDetailsFromProductId(cartDataEntry.getProductName());
if(productData.getProductName().equalsIgnoreCase(cartDataEntry.getProductName())){
cartDataEntry.setBasePrice(productData.getBasePrice());
cartDataEntry.setDiscout(productData.getDiscout());
cartDataEntry.setProductImagePath(productData.getProductImagePath());
productDataListForCart.add(cartDataEntry);
}
}
model.addAttribute("listOfProducts", productDataListForCart);
model.addAttribute("studentData", httpSession.getAttribute("student"));
if(productDataListForCart.isEmpty()){
model.addAttribute("isCartEmptyFlag", Boolean.TRUE);
}
return "CartPage";
}
This function displays cartPage and I want to display a link on this cart page so that if I click on that link the get page will be downloaded as a PDF file with the same format as it displayed in JSP page. This is how my page looks like, in case you're interested:
Spring Web MVC with PDF View Example outlines an approach. In summary, you implement a bean that extends Spring's AbstractView. This view accepts the model from Spring MVC which you can then use to render the PDF using the API of your choice. The article uses a ResourceBundleViewResolver to map the view name to a bean but I personally prefer to use a BeanNameViewResolver.
Spring does provide an AbstractPdfView class but use ann older version of iText for its implementation.

How to do a redirect in Spring MVC controller?

I am trying use a PRG (Post-Redirect-Get) pattern in one of my Spring MVC controller. The controller collects user data from an HTML form, does some processing, stores data in DB and then shows a JSP page. After saving data a redirect should happen and then the JSP page should be displayed.
I also tried to prepend "redirect:" in front of the VIEW_NAME but I get 404 then.
Please guide.
CartPageController.java
#Controller
#RequestMapping("/cartPageController.do")
public class CartPageController {
private static final Logger LOG = Logger.getLogger(CartPageController.class);
private static final String VIEW_NAME = "cart";
#Autowired
protected MasterDao masterDao;
#RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView processRequest(HttpServletRequest request, HttpServletResponse response) {
LOG.debug("Into the CartPageController...");
HttpSession session = request.getSession();
ModelAndView mav = new ModelAndView();
//create Cart object and store it in session
Cart cart = null;
if (session.getAttribute("cart") != null) {
cart = (Cart) session.getAttribute("cart");
} else {
cart = createCart();
session.setAttribute("cart", cart);
}
LOG.debug("cart = " + cart);
//determine the cart operation
String btnAddToCart = GenericUtils.nullToEmptyString(request.getParameter("btnAddToCart"));
String removeProduct = GenericUtils.nullToEmptyString(request.getParameter("removeProduct"));
String updateProduct = GenericUtils.nullToEmptyString(request.getParameter("updateProduct"));
LOG.debug("btnAddToCart = " + btnAddToCart);
LOG.debug("removeProduct = " + removeProduct);
LOG.debug("updateProduct = " + updateProduct);
if (btnAddToCart.length() > 0) {
addToCart(request, cart);
} else if (removeProduct.length() > 0) {
removeProduct(request, cart);
} else if (updateProduct.length() > 0) {
updateCart(request, cart);
}
//TODO: Should use PRG pattern here
//TRIED TO APPEND "redirect:" here but does not work, gives me 404
mav.setViewName(VIEW_NAME);
return mav;
}
//some more code below here
}
You should redirect to url not a view name. as Spring doc says:
While
the use of RedirectView works fine, if the controller itself creates
the RedirectView, there is no avoiding the fact that the controller is
aware that a redirection is happening. This is really suboptimal and
couples things too tightly. The controller should not really care
about how the response gets handled. In general it should operate only
in terms of view names that have been injected into it.
The special redirect: prefix allows you to accomplish this. If a view
name is returned that has the prefix redirect:, the
UrlBasedViewResolver (and all subclasses) will recognize this as a
special indication that a redirect is needed. The rest of the view
name will be treated as the redirect URL.
you can try
return new ModelAndView(new RedirectView("/page"));
You can't just prepend "redirect:" to your view name which results in redirect:cart and then obviously 404, what you have to do for redirect is to specify the redirect path for e.g.:
redirect:/cart.htm
This should explain it more in details.
You can do this way
redirect:cart.do and have requestmapping in controller which will return cart view.
Hope this will work.

Getting different data in ajax response froms second time

I am encountering a problem which I am not able to find out why.
I am using spring mvc and I am sending ajax request to one of my controller.
$.get("<c:url value="/createcomment" />", {id: pageid , newcomment : newcomment})
.done(function(data){
$("#newcomment"+data.pageId).val('');
var html = '<tr><td>'+
'<div class="pull-left">'+
'<img class="img-rounded" src="resources/profile-pics/male/small.jpg" alt="">'+
'</div><div class="span4"><ul class="nav nav-stacked">'+
'<li><font size="2"><i class="icon-user"></i>'+data.account.firstName+' '+data.account.lastName+'</font></li>'+
'<li><font size="2">'+data.text+'</font></li><li><font size="1">'+data.postingDate+
'</font></li></ul></div></td></tr>';
$(html).inserAfter($("#tr"+data.pageId));
}
When i refresh the page and send the request i get the following desired object.
and when I send it second time again i get Some Document Object.
I don't understand what is happening wrong.
#RequestMapping(value="/createcomment",method=RequestMethod.GET)
public #ResponseBody Comment createComment(#RequestParam(value="id")final String pageId,#RequestParam(value="newcomment")final String text,
final HttpServletRequest request ,final WebRequest req){
final Comment comment = new Comment();
comment.setId(GenerateUID.generate());
comment.setText(text);
comment.setPostingDate(new Date());
comment.setPageId(Long.valueOf(pageId));
try {
return comment;
} catch (NumberFormatException e) {
return null;
} catch (SignInNotFoundException e) {
return null;
}
}
Just for additonal information i am using jQuery JavaScript Library v1.7.1
You might want to check if your method throws a NumberFormatException or SignInNotFoundException, in which case it returns null. Your network log shows that 0 bytes of data have been transferred.

Display image in jsp using servlet

I am working on an application where the information of users gets added and modified(updated).
In add module, admin enters user details and unique-id(abc001) gets generated at "add" button. and admin also saves the image/picture(name : abc001) of the user in server location (//some-location-ip address/D drive/images).
In "update" module, admin can modify the user details, but can not modify id.
I need some direction in couple of scenarios.
If an Admin "updates" a particular user, the image of that user which is present in the server should gets displayed on the page as soon as the admin hit the update button.
Image code in JSP :
<img height="100px;" width="100px;" src="........." alt="Candidate Image"></img>
I have written a servlet, but don't know how to call different images corresponding to different users and display the image on the profile page.
user A profile will display user A image
user B profile will display user B image
and so on
Servlet code Snippet
public class UpDatePhoto extends HttpServlet {
public UpDatePhoto () {
super();
// TODO Auto-generated constructor stub
}
private static final long serialVersionUID = -8071854868821235857L;
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
private String imagePath;
*public void init() throws ServletException {
this.imagePath = "D:\\photo_not_available_large.png";
}*
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String requestedImage = request.getPathInfo();
if (requestedImage == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
return;
}
File image = new File(imagePath, URLDecoder.decode(requestedImage, "UTF-8"));
String contentType = getServletContext().getMimeType(image.getName());
if (contentType == null || !contentType.startsWith("image")) {
response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
return;
}
response.reset();
response.setBufferSize(DEFAULT_BUFFER_SIZE);
response.setContentType(contentType);
response.setHeader("Content-Length", String.valueOf(image.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + image.getName() + "\"");
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
input = new BufferedInputStream(new FileInputStream(image), DEFAULT_BUFFER_SIZE);
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} finally {
close(output);
close(input);
}
}
private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The image is not http accessible but is only accessible as a file, the servlet would have to open the image file, read in the contents and place those in the response buffer" ....not sure if i am correct.
Can somebody guide me to the direction and help me out as how to fetch the image from the server directory location and display the correct image for a user.
I have a hard time in understanding the concrete problem, but I believe that your root problem is that you don't know how to set the imagePath accordingly? It has namely a wrong value.The code shows that it should be set to the root folder where all images are been placed. In the underlying operating system platform, you need to map //some-location-ip address/D drive/images as a network drive in Windows explorer, e.g. Z: and then use that in your imagePath instead.
this.imagePath = "Z:";
It also expects the image file name as request pathinfo. So, assuming that your servlet is mapped on an URL pattern of /images/*, then your <img src> should look basically like this
<img src="images/filename.png" />
You could also fill it dynamically with EL. E.g. with the unique username of the logged-in user:
<img src="images/${user.name}.png" />
As to using the "D:\\photo_not_available_large.png" replacement image, you could set that when File#exists() returns false.

Play Framework: Image Display question

ref:
http://www.lunatech-research.com/playframework-file-upload-blob
I'm uneasy about one point in this example
#{list items:models.User.findAll(), as:'user'}
<img src="#{userPhoto(user.id)}">
#{/list}
At this point I'm already holding the user object (including the image blob). Yet the userPhoto() method makes another dip into the backend to get the Image user.photo
public static void userPhoto(long id) {
final User user = User.findById(id);
notFoundIfNull(user);
response.setContentTypeIfNotSet(user.photo.type());
renderBinary(user.photo.get());
}
Any way to avoid this unnecessary findById call?
You're not actually holding the user object any more though, because the userPhoto action is invoked in a separate request that's sent when the browser tries to load the image from the URL generated by #{userPhoto(user.id)}.
Of course, you could use the cache to store data from each user's photo Blob, which would reduce the likelihood that you had to go to the database on the image request. It's more trouble than it's worth in this case though since you're just doing a simple primary key lookup for the user object, and that should be relatively inexpensive. Plus Blobs aren't serializable, so you have to pull out each piece of information separately.
Still, if you were to try that it might look something like this:
// The action that renders your list of images
public static void index() {
List<User> users = User.findAll();
for (User user : users) {
cachePhoto(user.photo);
}
render(users);
}
// The action that returns the image data to display
public static void userPhoto(long id) {
InputStream photoStream;
String path = Cache.get("image_path_user_" + id);
String type = Cache.get("image_type_user_" + id);
// Was the data we needed in the cache?
if (path == null || type == null) {
// No, we'll have to go to the database anyway
User user = User.findById(id);
notFoundIfNull(user);
cachePhoto(user.photo);
photoStream = user.photo.get();
type = user.photo.type();
} else {
// Yes, just generate the stream directly
try {
photoStream = new FileInputStream(new File(path));
} catch (Exception ex) {
throw new UnexpectedException(ex);
}
}
response.setContentTypeIfNotSet(type);
renderBinary(photoStream);
}
// Convenience method for caching the photo information
private static void cachePhoto(Blob photo) {
if (photo == null) {
return;
}
Cache.set("image_path_user_" + user.id,
photo.getFile.getAbsolutePath());
Cache.set("image_type_user_" + user.id,
photo.getType());
}
Then you'd still have to worry about appropriately populating/invalidating the cache in your add, update, and delete actions too. Otherwise your cache would be polluted with stale data.

Resources