The path to a database with jee maven project - mysql

I'm currently making a website with Java EE, using maven, thymeleaf, and hosting it on heroku (database addon is JawsDBMySQL).
I've created a simple html page in order to check the good working of it.
Of course it works perfectly for a local upload : the file goes to a folder I've designed.
In my data base the path to my local storage is stored as a string.
I've also add a longblob column, but I did not really understood how to use it.
Now I want to store files into my database when my application is online.
I didn't found solution that perfectly match with my issue, but I'm quite sure it is pretty simple.
Hoping I have been clear enough,
thanks for your help.
Servlet that display a page on /home2 with the list of the pictures
package marquise.servlets;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import marquise.services.InformationLibrary;
#WebServlet("/home2")
public class HomeServlet extends AbstractGenericServlet2 {
private static final long serialVersionUID = 5402133218271984030L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
TemplateEngine templateEngine = this.createTemplateEngine(req);
WebContext context = new WebContext(req, resp, getServletContext());
//Country countryFilter = (Country) req.getSession().getAttribute("countryFilter");
context.setVariable("images", InformationLibrary.getInstance().listAllImages());
//context.setVariable("cities", CityService.getInstance().listAllCities(countryFilter));
//context.setVariable("countries", Country.values());
//context.setVariable("countryFilterSelected", countryFilter);
templateEngine.process("home", context, resp.getWriter());
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String countryString = req.getParameter("countryFilter");
resp.sendRedirect("home2");
}
}
Servlet for the path
#WebServlet("/imagepicture")
public class CityPictureServlet extends AbstractGenericServlet2 {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer imageId = Integer.parseInt(req.getParameter("id"));
Path picturePath = InformationLibrary.getInstance().getPicturePatch(imageId);
Files.copy(picturePath, resp.getOutputStream());
}
}
servlet that print image details (not important right now)
package marquise.servlets;
#WebServlet("/detail")
public class CityDetailServlet extends AbstractGenericServlet2 {
private static final long serialVersionUID = 8559083626521311046L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
TemplateEngine templateEngine = this.createTemplateEngine(req);
WebContext context = new WebContext(req, resp, getServletContext());
Integer idImage = Integer.parseInt(req.getParameter("id"));
context.setVariable("image", InformationLibrary.getInstance().getImage(idImage));
//context.setVariable("comments", InformationLibrary.getInstance().listCommentsByCity(idCity));
context.setVariable("comments", InformationLibrary.getInstance().listAllImages());
templateEngine.process("imagedetail", context, resp.getWriter());
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer cityId = Integer.parseInt(req.getParameter("id"));
resp.sendRedirect(String.format("detail?id=%d", cityId));
resp.sendRedirect("home2");
}
}
HTML page displaying the list of my images
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>City Explorer</title>
<link rel="stylesheet" href="bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="fontawesome/css/font-awesome.min.css">
<link rel="stylesheet" href="css/custom.css">
</head>
<body>
<header th:replace="~{common::header}"></header>
<div id="mainContent" class="container-fluid">
<section class="cityfilters">
<h3>Filters</h3>
<form class="form-inline" method="post">
<div class="form-group">
<label for="countryInput">Country</label>
<select class="form-control" id="countryInput" name="countryFilter">
<option value="">All countries</option>
<option th:each="country : ${countries}" th:value="${country}" th:selected="${countryFilterSelected} == ${country}">[[${country.label}]]</option>
</select>
</div>
<input type="submit" class="btn btn-default" value="Filter">
</form>
</section>
<section class="citylist">
<article class="citybox" th:each="image : ${images}">
<h3>
[[${image.name}]]
<a th:href="'deleteimage?id='+${image.id}" class="btn btn-xs btn-danger pull-right">
<i class="fa fa-times" aria-hidden="true"></i>
</a>
</h3>
<p th:text="${image.summary}" class="summary"></p>
<div class="btn-toolbar actionbar" role="toolbar">
<div class="btn-group" role="group">
<a th:href="'detail?id='+${image.id}" class="btn btn-primary"><i
class="fa fa-eye" aria-hidden="true"></i> See details</a>
</div>
</div>
<aside class="cityPhoto">
<img th:src="'imagepicture?id='+${image.id}" th:alt="'Vignette '+${image.name}">
</aside>
</article>
</section>
</div>
</body>
</html>
My Library Class with the path to my computer
public class InformationLibrary {
private static class InformationLibraryHolder{
private final static InformationLibrary instance = new InformationLibrary();
}
public static InformationLibrary getInstance(){
return InformationLibraryHolder.instance;
}
private InformationDao informationDao = new InformationDaoImpl();
private UtilisateurDao utilisateurDao = new UtilisateurDaoImpl();
private CommentaireDao commentaireDao = new CommentaireDaoImpl();
private ArticleDao articleDao = new ArticleDaoImpl();
private IdentifiantDao identifiantDao = new IdentifiantDaoImpl();
private ImageDao imageDao = new ImageDao();
private static final String PICTURE_MAIN_DIRECTORY = "/Users/louiscauvray/git/projet/src/main/resources";
private ElementsSiteDao elementsSiteDao = new ElementsSiteDao();
private InformationLibrary() {
}
//Recuperer les informations sur les utilisateurs
public List<Information> listFilms() {
return informationDao.listInformations();
}
public Information getInformation(Integer id) {
return informationDao.getInformation(id);
}
public Information addInformation(Information information) {
return informationDao.addInformation(information);
}
public List<Utilisateur> listUtilisateurs() {
return utilisateurDao.listUtilisateurs();
}
public Utilisateur getUtilisateur(Integer id) {
return utilisateurDao.getUtilisateur(id);
}
public Utilisateur getUtilisateurByNom(String nom){
return utilisateurDao.getUtilisateurByNom(nom);
}
public Utilisateur addUtilisateur(String nom, String prenom) {
return utilisateurDao.addUtilisateur(nom, prenom);
}
//Gerer les commentaires visible en backoffice
public List<Commentaire> listCommentaires(){
return commentaireDao.listCommentaires();
}
public Commentaire addCommentaire(String email ,String commentaire){
return commentaireDao.addCommentaire(email, commentaire);
}
public List<Article> listArticles(){
return articleDao.listArticles();
}
public Article addArticle(String title, String texte, LocalDate datePublication, String auteur) {
return articleDao.addArticle(title, texte, datePublication, auteur);
}
public Identifiant getIdentifiant(String login, String motDePasse){
return identifiantDao.getIdentifiant(login, motDePasse);
}
//Methode pour appeler les image et les chemins des images
public List<Image> listAllImages() {
return imageDao.listImages();
}
public Image getImage(Integer id) {
if(id == null) {
throw new IllegalArgumentException("Image id must be provided.");
}
return imageDao.getImage(id);
}
public void addImage(Image newImage, Part picture) throws IOException {
if(newImage == null){
throw new IllegalArgumentException("An image must be provided.");
}
if(newImage.getName() == null || "".equals(newImage.getName())) {
throw new IllegalArgumentException("An image must have a name.");
}
if(newImage.getSummary() == null || "".equals(newImage.getSummary())) {
throw new IllegalArgumentException("An image must have a summary.");
}
if(picture == null){
throw new IllegalArgumentException("An image must contain a picture.");
}
Path picturePath = Paths.get(PICTURE_MAIN_DIRECTORY, picture.getSubmittedFileName());
imageDao.addImage(newImage, picturePath.toString());
Files.copy(picture.getInputStream(), picturePath);
}
public Path getPicturePatch(Integer imageId) {
String picturePathString = imageDao.getPicturePath(imageId);
if(picturePathString == null) {
return getDefaultPicturePath();
} else {
Path picturePath = Paths.get(imageDao.getPicturePath(imageId));
if(Files.exists(picturePath)) {
return picturePath;
} else {
return getDefaultPicturePath();
}
}
}
private Path getDefaultPicturePath() {
try {
return Paths.get(this.getClass().getClassLoader().getResource("city-no-photo.png").toURI());
} catch (URISyntaxException e) {
return null;
}
}
// ElementsSite Dao
public void modifierElementTexte(String idElement, String contenuElement) {
elementsSiteDao.modifierElementTexte(idElement, contenuElement);
}
public void modifierElementImage(String idElement, String contenuElement, String cheminElement) {
elementsSiteDao.modifierElementImage(idElement, contenuElement, cheminElement);
}
public ElementsSite getElementById(String id) {
return elementsSiteDao.getElementById(id) ;
}
}
My Dao Class where methods to display images are defined
import marquise.daos.impl.DataSourceProvider;
import marquise.exceptions.CityExplorerRuntimeException;
import marquise.projos.Image;
public class ImageDao {
public List<Image> listImages() {
List<Image> images = new ArrayList<Image>();
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM image ORDER BY name")) {
while (resultSet.next()) {
images.add(
new Image(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("summary")));
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return images;
}
public Image getImage(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return new Image(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("summary"));
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
public void addImage(Image newImage, String picturePath) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("INSERT INTO image(name, summary, picture) VALUES (?, ?, ?)")) {
statement.setString(1, newImage.getName());
statement.setString(2, newImage.getSummary());
statement.setString(3, picturePath);
statement.executeUpdate();
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
}
public String getPicturePath(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT picture FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getString("picture");
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
}

Finally I found a solution to my problem :
I added a longblob column into my data base table, and changed a bit my method.
Here is my final code if you need it :
The DaoClass :
package marquise.daos;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import marquise.daos.impl.DataSourceProvider;
import marquise.exceptions.CityExplorerRuntimeException;
import marquise.projos.Image;
public class ImageDao {
public List<Image> listImages() {
List<Image> images = new ArrayList<Image>();
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM image ORDER BY name")) {
while (resultSet.next()) {
images.add(
new Image(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("summary")));
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return images;
}
public Image getImage(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return new Image(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("summary"));
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
public void addImage(Image newImage, String picturePath) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("INSERT INTO image(name, summary, picture) VALUES (?, ?, ?)")) {
statement.setString(1, newImage.getName());
statement.setString(2, newImage.getSummary());
statement.setString(3, picturePath);
statement.executeUpdate();
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
}
public void addImage(Image img, InputStream is){
try(Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("INSERT INTO image(name, summary, image) VALUES (?, ?, ?)")) {
statement.setString(1, img.getName());
statement.setString(2, img.getSummary());
statement.setBinaryStream(3, is);
statement.executeUpdate();
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
}
public String getPicturePath(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT picture FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getString("picture");
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
public InputStream getPicture(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT image FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getBinaryStream("image");
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}
/*public InputStream getPicture(Integer id) {
try (Connection connection = DataSourceProvider.getInstance().getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT image FROM image WHERE id = ?")) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getBlob("image") == null ? null : resultSet.getBlob("image").getBinaryStream();
}
}
} catch (SQLException e) {
throw new CityExplorerRuntimeException("Error when getting images", e);
}
return null;
}*/
}
the addimage servlet :
package marquise.servlets;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import marquise.projos.Image;
import marquise.services.InformationLibrary;
#WebServlet("/addimage")
#MultipartConfig
public class ImageAddServlet extends AbstractGenericServlet2 {
private static final long serialVersionUID = -3497793006266174453L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
TemplateEngine templateEngine = this.createTemplateEngine(req);
WebContext context = new WebContext(req, resp, getServletContext());
if(req.getSession().getAttribute("imageCreationError") != null) {
context.setVariable("errorMessage", req.getSession().getAttribute("imageCreationError"));
context.setVariable("image", (Image) req.getSession().getAttribute("imageCreationData"));
req.getSession().removeAttribute("imageCreationError");
req.getSession().removeAttribute("imageCreationData");
} else {
context.setVariable("image", new Image(null, null, null));
}
context.setVariable("countries", context);
templateEngine.process("connectedUsers/imageadd", context, resp.getWriter());
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String summary = req.getParameter("summary");
Part imagePicture = req.getPart("picture");
Image newImage = new Image(null, name, summary);
InputStream is = imagePicture.getInputStream();
try {
InformationLibrary.getInstance().addImage(newImage, is);
resp.sendRedirect("certificatsAdmin");
} catch (IllegalArgumentException|IOException e) {
req.getSession().setAttribute("imageCreationError", e.getMessage());
req.getSession().setAttribute("imageCreationData", newImage);
resp.sendRedirect("addimage");
}
}
}
The listImage servlet :
package marquise.servlets;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import marquise.services.InformationLibrary;
#WebServlet("/certificatsAdmin")
public class listeCertifServlet extends AbstractGenericServlet2 {
private static final long serialVersionUID = 5402133218271984030L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
HttpSession session=req.getSession(false);
if(session != null){}
else{
resp.sendRedirect("connexion");
out.println("Veuillez entre un mot de passe correct");
}
TemplateEngine templateEngine = this.createTemplateEngine(req);
WebContext context = new WebContext(req, resp, getServletContext());
//Country countryFilter = (Country) req.getSession().getAttribute("countryFilter");
context.setVariable("images", InformationLibrary.getInstance().listAllImages());
//context.setVariable("cities", CityService.getInstance().listAllCities(countryFilter));
//context.setVariable("countries", Country.values());
//context.setVariable("countryFilterSelected", countryFilter);
templateEngine.process("admin/certificatsAdmin", context, resp.getWriter());
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String countryString = req.getParameter("countryFilter");
resp.sendRedirect("certificatsAdmin");
}
}

Related

How to get random access to a file on SD-Card by means of API presented for Lollipop?

My application uses Java class RandomAccessFile to read/write bytes to a file on SD card randomly by means of realization of SeekableByteChannel interface. Now I need rewrite it for Android 5.0 with new Lollipop API.
I have found the only way to read:
InputStream inputStream = getContentResolver().openInputStream(uri);
and write:
ParcelFileDescriptor pfd = getActivity().getContentResolver().openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
from/to a file in new API.
I would like to have an ability to set channel in some random position and read/write bytes to that position. Is it possible to do that in new SDK 21? Does new SDK imply this way obtaining of channels:
FieInputChannel fieInputChannel = fileInputStream.getChannel();
FieOutputChannel fieOutputChannel = fileOutputStream.getChannel();
or some other approach?
It seems the only way to get a random read/write access to a file on SD card for SDK 21 (Lollipop) is as follows:
import android.content.Context;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import com.jetico.bestcrypt.FileManagerApplication;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class SecondaryCardChannel {//By analogy with the java.nio.channels.SeekableByteChannel
private FileChannel fileChannel;
private ParcelFileDescriptor pfd;
private boolean isInputChannel;
private long position;
public SecondaryCardChannel(Uri treeUri, Context context) {
try {
pfd = context.getContentResolver().openFileDescriptor(treeUri, "rw");
FileInputStream fis = new FileInputStream(pfd.getFileDescriptor());
fileChannel = fis.getChannel();
isInputChannel = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public int read(ByteBuffer buffer) {
if (!isInputChannel) {
try {
fileChannel.close();
FileInputStream fis = new FileInputStream(pfd.getFileDescriptor());
fileChannel = fis.getChannel();
isInputChannel = true;
} catch (IOException e) {
e.printStackTrace();
}
}
try {
fileChannel.position(position);
int bytesRead = fileChannel.read(buffer);
position = fileChannel.position();
return bytesRead;
} catch (IOException e) {
e.printStackTrace();
return -1;
}
}
public int write(ByteBuffer buffer) {
if (isInputChannel) {
try {
fileChannel.close();
FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor());
fileChannel = fos.getChannel();
isInputChannel = false;
} catch (IOException e) {
e.printStackTrace();
}
}
try {
fileChannel.position(position);
int bytesWrite = fileChannel.write(buffer);
position = fileChannel.position();
return bytesWrite;
} catch (IOException e) {
e.printStackTrace();
return -1;
}
}
public long position() throws IOException {
return position;
}
public SecondaryCardChannel position(long newPosition) throws IOException {
position = newPosition;
return this;
}
public long size() throws IOException {
return fileChannel.size();
}
public SecondaryCardChannel truncate(long size) throws IOException {
fileChannel.truncate(size);
return this;
}
}
EDIT 15/03/2017:
Little bit optimized version looks like
import android.content.Context;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class SecondaryCardChannel {
private ParcelFileDescriptor pfdInput, pfdOutput;
private FileInputStream fis;
private FileOutputStream fos;
private long position;
public SecondaryCardChannel(Uri treeUri, Context context) {
try {
pfdInput = context.getContentResolver().openFileDescriptor(treeUri, "r");
pfdOutput = context.getContentResolver().openFileDescriptor(treeUri, "rw");
fis = new FileInputStream(pfdInput.getFileDescriptor());
fos = new FileOutputStream(pfdOutput.getFileDescriptor());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public int read(ByteBuffer buffer) {
try {
FileChannel fch = fis.getChannel();
fch.position(position);
int bytesRead = fch.read(buffer);
position = fch.position();
return bytesRead;
} catch (IOException e) {
e.printStackTrace();
return -1;
}
}
public int write(ByteBuffer buffer) {
try {
FileChannel fch = fos.getChannel();
fch.position(position);
int bytesWrite = fch.write(buffer);
position = fch.position();
return bytesWrite;
} catch (IOException e) {
e.printStackTrace();
return -1;
}
}
public long position() throws IOException {
return position;
}
public SecondaryCardChannel position(long newPosition) throws IOException {
position = newPosition;
return this;
}
public long size() throws IOException {
return fis.getChannel().size();
}
public void force(boolean metadata) throws IOException {
fos.getChannel().force(metadata);
pfdOutput.getFileDescriptor().sync();
}
public long truncate(long size) throws Exception {
FileChannel fch = fos.getChannel();
try {
fch.truncate(size);
return fch.size();
} catch (Exception e){ // Attention! Truncate is broken on removable SD card of Android 5.0
e.printStackTrace();
return -1;
}
}
public void close() throws IOException {
FileChannel fch = fos.getChannel();
fch.close();
fos.close();
fis.close();
pfdInput.close();
pfdOutput.close();
}
}

Getting Connection Reset when lost connection with Smack API

i implement a small client which runs as bot on my Server.
I test the reconnect method and cut the internet connection.
I always get this error when i establish the connection again:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.read1(BufferedReader.java:205)
at java.io.BufferedReader.read(BufferedReader.java:279)
at org.xmlpull.mxp1.MXParser.fillBuf(MXParser.java:2992)
at org.xmlpull.mxp1.MXParser.more(MXParser.java:3046)
at org.xmlpull.mxp1.MXParser.nextImpl(MXParser.java:1144)
at org.xmlpull.mxp1.MXParser.next(MXParser.java:1093)
at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:325)
at org.jivesoftware.smack.PacketReader.access$000(PacketReader.java:43)
at org.jivesoftware.smack.PacketReader$1.run(PacketReader.java:70)
This is my Jabber-Manager Class:
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;
import java.io.IOException;
import java.util.Scanner;
public class JabberSmackApi extends Thread {
private static final int packetReplyTimeout = 500; // millis
private String server;
private ConnectionConfiguration config;
private XMPPConnection connection;
private ChatManager chatManager;
private MessageListener messageListener;
private String user;
public JabberSmackApi(String server) {
this.server = server;
}
public static boolean stopValue = true;
#Override
public void run() {
try {
init();
performLogin("Test#jabber.de", "password");
setStatus(true, "Hiiiii!!!!");
user = "otherUser#jabber.de";
String name = "otherUser";
createEntry(user, name);
sendMessage("Hello mate", user);
while(stopValue) {
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopMe() {
this.stopValue = false;
}
public void init() throws XMPPException {
System.out.println(String.format("Initializing connection to server %1$s", server));
SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);
config = new ConnectionConfiguration(server);
config.setReconnectionAllowed(true);
connection = new XMPPConnection(config);
connection.connect();
System.out.println("Connected: " + connection.isConnected());
chatManager = connection.getChatManager();
messageListener = new MyMessageListener();
}
public void performLogin(String username, String password) throws XMPPException {
if (connection!=null && connection.isConnected()) {
connection.login(username, password);
}
}
public void setStatus(boolean available, String status) {
Presence.Type type = available? Type.available: Type.unavailable;
Presence presence = new Presence(type);
presence.setStatus(status);
connection.sendPacket(presence);
}
public void destroy() {
if (connection!=null && connection.isConnected()) {
connection.disconnect();
}
}
public void sendMessage(String message, String buddyJID) throws XMPPException {
System.out.println(String.format("Sending mesage '%1$s' to user %2$s", message, buddyJID));
Chat chat = chatManager.createChat(buddyJID, messageListener);
chat.sendMessage(message);
}
public void createEntry(String user, String name) throws Exception {
System.out.println(String.format("Creating entry for buddy '%1$s' with name %2$s", user, name));
Roster roster = connection.getRoster();
roster.createEntry(user, name, null);
}
class MyMessageListener implements MessageListener {
#Override
public void processMessage(Chat chat, Message message) {
String from = message.getFrom();
String body = message.getBody();
System.out.println(String.format("Received message '%1$s' from %2$s", body, from));
}
}
}

EJB - JPA - Hibernate - JBoss 6-MySql

I am deleveloping web project EJB,JPA - Hibernate as provider, JBoss 6,MySql.
I new in EJB, JPA.I have problems with load ejb bean in servlet.
persistence.xml
<persistence-unit name="LibraryPersistenceUnit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MySqlDS</jta-data-source>
<class>library.entity.User</class>
<class>library.entity.Book</class>
<properties>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
UserFacade.java
#Local
public interface UserFacade {
User findUserByLoginAndPassword(String login, String password);
/* List<User> getClients();
void returnBooks(long userId, long[] ids);
void takeBooks(long userId, long[] ids);*/
}
UserFacadeImpl.java
package library.facades.impl;
import library.dao.impl.UserDAO;
import library.entity.User;
import library.facades.interfaces.UserFacade;
import javax.ejb.EJB;
import javax.ejb.Stateless;
#Stateless
public class UserFacadeImpl implements UserFacade {
#EJB
private UserDAO userDAO;
public UserFacadeImpl() {
}
public User findUserByLoginAndPassword(String login, String password) {
User user = userDAO.selectUserByLoginAndPassword(login, password);
return user;
}
/* public List<User> getListClients() {
List<User> userList = userDAO.getClients();
return userList;
}
public void returnBooks(long userId, long[] ids) {
userDAO.returnBooks(userId, ids);
}
public void takeBooks(long userId, long[] ids) {
userDAO.takeBooks(userId, ids);
}*/
}
UserDAO.java
package library.dao.impl;
import library.dao.interfaces.GenericDAO;
import library.entity.User;
import javax.ejb.Local;
import javax.ejb.Stateless;
import java.util.HashMap;
import java.util.Map;
#Stateless
public class UserDAO extends GenericDAO {
public UserDAO() {
super(User.class);
}
public User selectUserByLoginAndPassword(String login, String password) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("login", login);
parameters.put("password", password);
return (User) super.findOneResult(User.SELECT_USER_BY_LOGIN_AND_PASSWORD, parameters);
}
/*public List<User> getClients() {
Query namedQuery = entityManager.createNamedQuery(User.ALL_CLIENTS, User.class);
List<User> clientsList = namedQuery.getResultList();
return clientsList;
}
#Override
public void returnBooks(long userId, long[] ids) {
User user = entityManager.find(User.class, userId);
for (long id : ids) {
Book book = entityManager.find(Book.class, id);
user.getTakenBooks().remove(book);
}
entityManager.merge(user);
}
#Override
public void takeBooks(long userId, long[] ids) {
User user = entityManager.find(User.class, userId);
for (long id : ids) {
Book book = entityManager.find(Book.class, id);
user.getTakenBooks().add(book);
}
entityManager.merge(user);
}*/
}
GenericDAO.java
package library.dao.interfaces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;
import java.util.Map;
public abstract class GenericDAO<T> {
private static final String LIBRARY_PERSISTENCE_UNIT = "LibraryPersistenceUnit";
#PersistenceContext(unitName = LIBRARY_PERSISTENCE_UNIT)
private EntityManager entityManager;
private Class<T> entityClass;
public GenericDAO() {
}
public GenericDAO(Class<T> entityClass) {
this.entityClass = entityClass;
}
public void save(T entity) {
entityManager.persist(entity);
}
protected void delete(Object id, Class<T> classe) {
T entityToBeRemoved = entityManager.getReference(classe, id);
entityManager.remove(entityToBeRemoved);
}
public T update(T entity) {
return entityManager.merge(entity);
}
public T find(int entityID) {
return entityManager.find(entityClass, entityID);
}
// Using the unchecked because JPA does not have a
// entityManager.getCriteriaBuilder().createQuery()<T> method
#SuppressWarnings({"unchecked", "rawtypes"})
public List<T> findAll() {
/* CriteriaQuery cq = entityManager.getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));*/
return null;//entityManager.createQuery(cq).getResultList();
}
// Using the unchecked because JPA does not have a
// ery.getSingleResult()<T> method
#SuppressWarnings("unchecked")
protected T findOneResult(String namedQuery, Map<String, Object> parameters) {
T result = null;
try {
Query query = entityManager.createNamedQuery(namedQuery);
// Method that will populate parameters if they are passed not null and empty
if (parameters != null && !parameters.isEmpty()) {
populateQueryParameters(query, parameters);
}
result = (T) query.getSingleResult();
} catch (Exception e) {
System.out.println("Error while running query: " + e.getMessage());
e.printStackTrace();
}
return result;
}
private void populateQueryParameters(Query query, Map<String, Object> parameters) {
for (Map.Entry<String, Object> entry : parameters.entrySet()) {
query.setParameter(entry.getKey(), entry.getValue());
}
}
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
LibraryController
package library.controller;
import library.entity.User;
import library.facades.interfaces.UserFacade;
import library.resourses.constants.Constants;
import library.resourses.enums.Role;
import javax.ejb.EJB;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LibraryController extends HttpServlet {
#EJB
private UserFacade userFacade;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException {
performAction(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException {
performAction(request, response);
}
private void performAction(HttpServletRequest request, HttpServletResponse response) {
String pageType = request.getParameter(Constants.PAGE_TYPE);
if (pageType != null) {
try {
String page = null;
String login = request.getParameter(Constants.USER_LOGIN);
String password = request.getParameter(Constants.USER_PASSWORD);
User user = userFacade.findUserByLoginAndPassword(login, password);
if (user == null) {
request.getSession().setAttribute(Constants.ERROR,
Constants.ERROR_MESSAGE_7);
page = Constants.MAIN_PAGE;
} else {
String namePage = user.getRole().toString().toLowerCase();
if (isClient(user)) {
request.getSession().setAttribute(Constants.CLIENT,
user);
request.getSession().setAttribute(Constants.ERROR, null);
} else if (isAdministrator(user)) {
request.getSession().setAttribute(Constants.ADMINISTRATOR,
user);
request.getSession().setAttribute(Constants.ERROR, null);
}
page = Constants.START_PAGES + namePage + Constants.END_PAGES;
}
RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher(page);
requestDispatcher.forward(request, response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private boolean isAdministrator(User user) {
return user.getRole().equals(Role.ADMINISTRATOR);
}
private boolean isClient(User user) {
return user.getRole().equals(Role.CLIENT);
}
}
I get null for userFacade.Can you explain me what I do wrong.
Thanks.
The problem is that instead of letting the container instantiate and inject the DAO for you, you explicitely create the DAO instance by yourself:
private IUserDAO dao;
public UserService() {
dao = UserDAOImpl.getInstance();
}
For the EntityManager to be injected into the DAO, the container must instantiate it, not you. Replace the above code with the following, which uses dependency injection, and will thus also have the advantage of making your code testable:
#Inject
private IUserDAO dao;

Store enums in database using hibernate

I need to store an object using Hibernate, but this object use an enum. I can store, but when I tried to retrieve it again, this fails with this error: "Studies is not mapped [FROM Studies]".
I tried with a lot of solutions in internet but nothing works. I use MySQL database
This is the enum:
public enum StudyStatus {
Created("Created"), Started("Started"), Closed("Closed");
private final String value;
StudyStatus(String value){
this.value = value;
}
public static StudyStatus fromValue(int value){
for (StudyStatus status : values()) {
if (status.value.equals(value)) {
return status;
}
}
throw new IllegalArgumentException("Invalid status: " + value);
}
public String toValue(){
return value;
}
}
This is the EnumUserType class
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.AbstractStandardBasicType;
import org.hibernate.type.IntegerType;
import org.hibernate.type.StringType;
import org.hibernate.usertype.EnhancedUserType;
import org.hibernate.usertype.ParameterizedType;
public abstract class AbstractEnumUserType<E extends Enum<E>, V> implements
EnhancedUserType, ParameterizedType {
public static int DEAFAULT_SQL_TYPE = Types.INTEGER;
private PreparedStatementSetter psSetter;
private AbstractStandardBasicType<?> basicType;
protected abstract Class<E> getEnumClass();
protected abstract Class<V> getValueClass();
protected abstract E convertEnum(V rawValue);
protected abstract V convertSqlValue(E enumValue);
protected int getSqlType() {
int sqlType = Types.OTHER;
switch (getValueClass().getName()) {
case "java.lang.String":
sqlType = Types.VARCHAR;
break;
case "java.lang.Integer":
sqlType = Types.INTEGER;
break;
default:
break;
}
return sqlType;
}
// ////////////////////////////
#Override
public int[] sqlTypes() {
return new int[] { getSqlType() };
}
#Override
public Class<?> returnedClass() {
return getEnumClass();
}
#Override
public boolean equals(Object x, Object y) throws HibernateException {
return (x == y);
}
#Override
public int hashCode(Object x) throws HibernateException {
return (x == null) ? 0 : x.hashCode();
}
#Override
public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner)
throws HibernateException, SQLException {
Object rawValue = basicType.nullSafeGet(rs, names[0], session, owner);
Object enumValue = (rawValue == null) ? null
: convertEnum((V) rawValue);
return enumValue;
}
#Override
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.VARCHAR);
} else {
psSetter.set(st, convertSqlValue((E) value), index);
}
}
#Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
#Override
public boolean isMutable() {
return false;
}
#Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
#Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
#Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
#Override
public void setParameterValues(Properties parameters) {
// Initialize Method
initBasicType();
initPreparedStatementSetter();
}
#Override
public String objectToSQLString(Object value) {
return '\'' + ((Enum<?>) value).name() + '\'';
}
#Override
public String toXMLString(Object value) {
return ((Enum<?>) value).name();
}
#Override
public Object fromXMLString(String xmlValue) {
// TODO
throw new IllegalAccessError();
// return Enum.valueOf(, xmlValue);
}
protected void initBasicType() {
switch (getSqlType()) {
case Types.VARCHAR:
basicType = StringType.INSTANCE;
break;
case Types.INTEGER:
basicType = IntegerType.INSTANCE;
break;
default:
break;
}
}
protected void initPreparedStatementSetter() {
// TODO
switch (getSqlType()) {
case Types.VARCHAR:
psSetter = new StringPreparedStatementSetter();
break;
case Types.INTEGER:
psSetter = new IntPreparedStatementSetter();
default:
break;
}
}
private static interface PreparedStatementSetter {
void set(PreparedStatement st, Object value, int index)
throws SQLException;
}
private static class StringPreparedStatementSetter implements
PreparedStatementSetter {
#Override
public void set(PreparedStatement st, Object value, int index) {
try {
st.setString(index, (String) value);
} catch (SQLException e) {
}
}
}
private static class IntPreparedStatementSetter implements
PreparedStatementSetter {
#Override
public void set(PreparedStatement st, Object value, int index) {
try {
st.setInt(index, (Integer) value);
} catch (SQLException e) {
}
}
}
}
The class with the enum
import java.util.ArrayList;
import ateam.capi.common.enums.StudyStatus;
public class Study {
private String id;
private String name;
private StudyStatus status;
private ArrayList<User> pollsters;
private Questionnaire actualQuestionnaire;
public Questionnaire getActualQuestionnaire() {
return actualQuestionnaire;
}
public void setActualQuestionnaire(Questionnaire actualQuestionnaire) {
this.actualQuestionnaire = actualQuestionnaire;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public StudyStatus getStatus() {
return status;
}
public void setStatus(StudyStatus status) {
this.status = status;
}
public ArrayList<User> getPollsters() {
return pollsters;
}
public void setPollsters(ArrayList<User> pollsters) {
this.pollsters = pollsters;
}
}
This is the XML to map the Study class
<hibernate-mapping package="ateam.capi.common.beans">
<class name="Study" table="Studies">
<id name="id" column="id"></id>
<property name="name"/>
<property name="status">
<type name="ateam.capi.capipersistence.utils.EnumUserType">
<param name="enumClassName">
ateam.capi.common.enums.StudyStatus
</param>
</type>
</property>
</class>
</hibernate-mapping>
Study DAO class
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import ateam.capi.capipersistence.utils.HibernateUtil;
import ateam.capi.common.beans.Questionnaire;
import ateam.capi.common.beans.Study;
public class DAO_Study {
private Session session;
private Transaction tx;
public void saveStudy(Study study) throws HibernateException{
try{
initOperations();
session.save(study);
tx.commit();
} catch (HibernateException ex){
handleException(ex);
throw ex;
} finally{
if (session!=null){
session.close();
}
}
}
public void deleteStudy(Study study) throws HibernateException{
try{
initOperations();
this.session.delete(study);
this.tx.commit();
} catch (HibernateException ex){
handleException(ex);
throw ex;
} finally{
if (session!=null){
session.close();
}
}
}
public List<Study> getStudiesList() throws HibernateException{
List<Study> studiesList = null;
try{
initOperations();
String hql = "FROM Studies";
Query query = session.createQuery(hql);
studiesList = query.list();
} catch (HibernateException ex){
handleException(ex);
throw ex;
} finally{
if (session!=null){
session.close();
}
}
return studiesList;
}
private void initOperations() throws HibernateException{
HibernateUtil.createSession();
this.session = HibernateUtil.getSessionFactory().openSession();
this.tx = this.session.beginTransaction();
}
private void handleException(HibernateException ex) throws HibernateException{
this.tx.rollback();
System.out.println(ex.getStackTrace());
throw ex;
}
}
I use Java7 with hibernate 4.1.8, I found other solutions but dont work in java7
Any Idea?
Thanks!
Shouldn't your query look like from study instead of from studies? Studies is the table not the defined entity.

Spring REST service: retrieving JSON from Request

I am building a REST service on Spring 3.1. I am using #EnableWebMVC annotation for that. Since my service will only be accepting JSON requests, I would also like to dump the incoming request into a MongoDB collection for logging (and, later, for data transformation). I would like to access the raw JSON Request (which I could do on a non-spring implementation using "#Content HttpServletRequest request" as a method parameter).
I am a Spring newbie. So, kindly help me with directions to achieve this. Thanks!
UPDATE: The issue is not completely resolved. Only my tests with GET worked. It fails with POST. Therefore unchecked the accepted answer
The issue is, even if I create a HttpServletRequestWrapper, I cannot forward the request after I process and wrap the request. Here is what happens:
Interceptor:
public class DBLogInterceptor extends HandlerInterceptorAdapter {
MyRequestWrapper requestWrapper;
private final static Logger logger = Logger.getLogger(DBLogInterceptor.class);
#Override
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception
{
requestWrapper = new MyRequestWrapper(request);
// Code removed, but it just dumps requestWrapper.getBody() into DB
return super.preHandle(requestWrapper, response, handler);
}
}
HTTP POST Servicing method
#RequestMapping(method = RequestMethod.POST, consumes="application/json", produces="application/json", value = "employee")
#ResponseBody
public String updateEntity(#RequestBody Employee emp) {
// Do some DB Stuff. Anyway, the control flow does not reach this place.
return "Employee " + emp.getName() + " updated successfully!";
}
Now I get an exception whenever I send a POST:
12:04:53,821 DEBUG DBLogInterceptor:22 - {"name":"Van Damme","dept":"Applied Martial Arts"}
12:04:53,843 DEBUG RequestResponseBodyMethodProcessor:117 - Reading [com.test.webapp.login.domain.Employee] as "application/json" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter#154174f9]
12:04:53,850 DEBUG ExceptionHandlerExceptionResolver:132 - Resolving exception from handler [public java.lang.String com.test.webapp.controller.EmployeeService.updateEntity(com.test.webapp.login.domain.Employee)]: java.io.IOException: Stream closed
12:04:53,854 DEBUG ResponseStatusExceptionResolver:132 - Resolving exception from handler [public java.lang.String com.test.webapp.controller.EmployeeService.updateEntity(com.test.webapp.login.domain.Employee)]: java.io.IOException: Streamclosed
12:04:53,854 DEBUG DefaultHandlerExceptionResolver:132 - Resolving exception from handler [public java.lang.String com.test.webapp.controller.EmployeeService.updateEntity(com.test.webapp.login.domain.Employee)]: java.io.IOException: Streamclosed
12:04:53,859 DEBUG DispatcherServlet:910 - Could not complete request
java.io.IOException: Stream closed
at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:312)
at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:200)
at org.codehaus.jackson.impl.ByteSourceBootstrapper.ensureLoaded(ByteSourceBootstrapper.java:507)
at org.codehaus.jackson.impl.ByteSourceBootstrapper.detectEncoding(ByteSourceBootstrapper.java:129)
at org.codehaus.jackson.impl.ByteSourceBootstrapper.constructParser(ByteSourceBootstrapper.java:224)
at org.codehaus.jackson.JsonFactory._createJsonParser(JsonFactory.java:785)
at org.codehaus.jackson.JsonFactory.createJsonParser(JsonFactory.java:561)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1914)
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:124)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:153)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:120)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:91)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:71)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:75)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:156)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I expected the HttpServletRequestWrapper to be taking care of caching the request. But it doesn't happen somehow.
Using the HttpServletRequest object, you can get access to the URL the client used to make the request, the method used (GET, POST, PUT, etc), the query string, and headers.
Getting the RequestBody may be a bit trickier and may require using the HttpServletRequestWrapper object. Since the request body can only be read once, you'll need to extend the wrapper to access it so that your target controller can still access it later to deserialize your JSON into POJO objects.
public class MyRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public MyRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
}
To access the requests in a central location, you can use either a Filter or a Spring Interceptor. Both of these are invoked prior to the request being delegated to the controller, and both have access to the servlet.
Here is an actual Logging example using a Spring Interceptor:
package com.vaannila.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler. HandlerInterceptorAdapter;
public class LoggerInterceptor extends HandlerInterceptorAdapter {
static Logger logger = Logger.getLogger(LoggerInterceptor.class);
static {
BasicConfigurator.configure();
}
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
logger.info("Before handling the request");
return super.preHandle(request, response, handler);
}
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
logger.info("After handling the request");
super.postHandle(request, response, handler, modelAndView);
}
#Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
logger.info("After rendering the view");
super.afterCompletion(request, response, handler, ex);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="viewResolver" class="org.springframework.web.servlet.view. InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
<bean id="handlerMapping" class="org.springframework.web.servlet.handler. BeanNameUrlHandlerMapping" p:interceptors-ref="loggerInterceptor" />
<bean id="loggerInterceptor" class="com.vaannila.interceptor.LoggerInterceptor" />
<bean id="userService" class="com.vaannila.service.UserServiceImpl" />
<bean name="/userRegistration.htm" class="com.vaannila.web.UserController" p:userService-ref="userService" p:formView="userForm" p:successView="userSuccess" />
</beans>
In the LoggerInterceptor, you could use the following code to access the request:
MyRequestWrapper myRequestWrapper = new MyRequestWrapper((HttpServletRequest) request);
String body = myRequestWrapper.getBody();
String clientIP = myRequestWrapper.getRemoteHost();
int clientPort = request.getRemotePort();
String uri = myRequestWrapper.getRequestURI();
System.out.println(body);
System.out.println(clientIP);
System.out.println(clientPort);
System.out.println(uri);
I doubt if HttpServletRequestWrapper can ever work... Take a look at the DispatcherServlet implementation:
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
if (interceptors != null) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
return;
}
interceptorIndex = i;
}
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
It passes reference to "processedRequest" still, which refers to a HttpServletRequest request whose stream has already been read.
I know this is an old question, but for those of you that are still looking for a solution, this worked for me:
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.output.TeeOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpLoggingFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(HttpLoggingFilter.class);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
Map<String, String> requestMap = this
.getTypesafeRequestMap(httpServletRequest);
BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(
httpServletRequest);
BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper(
httpServletResponse);
final StringBuilder logMessage = new StringBuilder(
"REST Request - ").append("[HTTP METHOD:")
.append(httpServletRequest.getMethod())
.append("] [PATH INFO:")
.append(httpServletRequest.getPathInfo())
.append("] [REQUEST PARAMETERS:").append(requestMap)
.append("] [REQUEST BODY:")
.append(bufferedRequest.getRequestBody())
.append("] [REMOTE ADDRESS:")
.append(httpServletRequest.getRemoteAddr()).append("]");
chain.doFilter(bufferedRequest, bufferedResponse);
logMessage.append(" [RESPONSE:")
.append(bufferedResponse.getContent()).append("]");
logger.debug(logMessage.toString());
} catch (Throwable a) {
logger.error(a.getMessage());
}
}
private Map<String, String> getTypesafeRequestMap(HttpServletRequest request) {
Map<String, String> typesafeRequestMap = new HashMap<String, String>();
Enumeration<?> requestParamNames = request.getParameterNames();
while (requestParamNames.hasMoreElements()) {
String requestParamName = (String) requestParamNames.nextElement();
String requestParamValue = request.getParameter(requestParamName);
typesafeRequestMap.put(requestParamName, requestParamValue);
}
return typesafeRequestMap;
}
#Override
public void destroy() {
}
private static final class BufferedRequestWrapper extends
HttpServletRequestWrapper {
private ByteArrayInputStream bais = null;
private ByteArrayOutputStream baos = null;
private BufferedServletInputStream bsis = null;
private byte[] buffer = null;
public BufferedRequestWrapper(HttpServletRequest req)
throws IOException {
super(req);
// Read InputStream and store its content in a buffer.
InputStream is = req.getInputStream();
this.baos = new ByteArrayOutputStream();
byte buf[] = new byte[1024];
int read;
while ((read = is.read(buf)) > 0) {
this.baos.write(buf, 0, read);
}
this.buffer = this.baos.toByteArray();
}
#Override
public ServletInputStream getInputStream() {
this.bais = new ByteArrayInputStream(this.buffer);
this.bsis = new BufferedServletInputStream(this.bais);
return this.bsis;
}
String getRequestBody() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(
this.getInputStream()));
String line = null;
StringBuilder inputBuffer = new StringBuilder();
do {
line = reader.readLine();
if (null != line) {
inputBuffer.append(line.trim());
}
} while (line != null);
reader.close();
return inputBuffer.toString().trim();
}
}
private static final class BufferedServletInputStream extends
ServletInputStream {
private ByteArrayInputStream bais;
public BufferedServletInputStream(ByteArrayInputStream bais) {
this.bais = bais;
}
#Override
public int available() {
return this.bais.available();
}
#Override
public int read() {
return this.bais.read();
}
#Override
public int read(byte[] buf, int off, int len) {
return this.bais.read(buf, off, len);
}
}
public class TeeServletOutputStream extends ServletOutputStream {
private final TeeOutputStream targetStream;
public TeeServletOutputStream(OutputStream one, OutputStream two) {
targetStream = new TeeOutputStream(one, two);
}
#Override
public void write(int arg0) throws IOException {
this.targetStream.write(arg0);
}
public void flush() throws IOException {
super.flush();
this.targetStream.flush();
}
public void close() throws IOException {
super.close();
this.targetStream.close();
}
}
public class BufferedResponseWrapper implements HttpServletResponse {
HttpServletResponse original;
TeeServletOutputStream tee;
ByteArrayOutputStream bos;
public BufferedResponseWrapper(HttpServletResponse response) {
original = response;
}
public String getContent() {
return bos.toString();
}
public PrintWriter getWriter() throws IOException {
return original.getWriter();
}
public ServletOutputStream getOutputStream() throws IOException {
if (tee == null) {
bos = new ByteArrayOutputStream();
tee = new TeeServletOutputStream(original.getOutputStream(),
bos);
}
return tee;
}
#Override
public String getCharacterEncoding() {
return original.getCharacterEncoding();
}
#Override
public String getContentType() {
return original.getContentType();
}
#Override
public void setCharacterEncoding(String charset) {
original.setCharacterEncoding(charset);
}
#Override
public void setContentLength(int len) {
original.setContentLength(len);
}
#Override
public void setContentType(String type) {
original.setContentType(type);
}
#Override
public void setBufferSize(int size) {
original.setBufferSize(size);
}
#Override
public int getBufferSize() {
return original.getBufferSize();
}
#Override
public void flushBuffer() throws IOException {
tee.flush();
}
#Override
public void resetBuffer() {
original.resetBuffer();
}
#Override
public boolean isCommitted() {
return original.isCommitted();
}
#Override
public void reset() {
original.reset();
}
#Override
public void setLocale(Locale loc) {
original.setLocale(loc);
}
#Override
public Locale getLocale() {
return original.getLocale();
}
#Override
public void addCookie(Cookie cookie) {
original.addCookie(cookie);
}
#Override
public boolean containsHeader(String name) {
return original.containsHeader(name);
}
#Override
public String encodeURL(String url) {
return original.encodeURL(url);
}
#Override
public String encodeRedirectURL(String url) {
return original.encodeRedirectURL(url);
}
#SuppressWarnings("deprecation")
#Override
public String encodeUrl(String url) {
return original.encodeUrl(url);
}
#SuppressWarnings("deprecation")
#Override
public String encodeRedirectUrl(String url) {
return original.encodeRedirectUrl(url);
}
#Override
public void sendError(int sc, String msg) throws IOException {
original.sendError(sc, msg);
}
#Override
public void sendError(int sc) throws IOException {
original.sendError(sc);
}
#Override
public void sendRedirect(String location) throws IOException {
original.sendRedirect(location);
}
#Override
public void setDateHeader(String name, long date) {
original.setDateHeader(name, date);
}
#Override
public void addDateHeader(String name, long date) {
original.addDateHeader(name, date);
}
#Override
public void setHeader(String name, String value) {
original.setHeader(name, value);
}
#Override
public void addHeader(String name, String value) {
original.addHeader(name, value);
}
#Override
public void setIntHeader(String name, int value) {
original.setIntHeader(name, value);
}
#Override
public void addIntHeader(String name, int value) {
original.addIntHeader(name, value);
}
#Override
public void setStatus(int sc) {
original.setStatus(sc);
}
#SuppressWarnings("deprecation")
#Override
public void setStatus(int sc, String sm) {
original.setStatus(sc, sm);
}
#Override
public String getHeader(String arg0) {
return original.getHeader(arg0);
}
#Override
public Collection<String> getHeaderNames() {
return original.getHeaderNames();
}
#Override
public Collection<String> getHeaders(String arg0) {
return original.getHeaders(arg0);
}
#Override
public int getStatus() {
return original.getStatus();
}
}
}
Then simply register the filter in web.xml and you're done. All credits to: http://wetfeetblog.com/servlet-filer-to-log-request-and-response-details-and-payload/431 (I just did some minor fix to it).
Hey can you try with this:
#RequestMapping(method = RequestMethod.POST, consumes="application/json", produces="application/json", value = "/employee")
#ResponseBody
public String updateEntity(#RequestBody Employee emp) {
// Do some DB Stuff. Anyway, the control flow does not reach this place.
return "Employee " + emp.getName() + " updated successfully!";
}
Here: it you proving URI with the '/' it allows all the operations to perform. such as get post update and delete with same URI value.
Currently in spring-mvc repo, interceptors are invoked in DispatcherServlet#doDispatch(...):
https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java
...
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
try {
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
...
Can I define my own DispatcherServlet, and override doDispatch(...) to inject a HttpRequestWrapper with a ByteArrayInputStream on getInputStream()?
...
#Override
protected void doDispatch(HttpServletRequest request, HttpServletResponse response)
throws Exception {
RequestWrapper wrappedRequest = new RequestWrapper(request);
logger.debug("injecting RequestWrapper: " + wrappedRequest);
super.doDispatch(wrappedRequest, response);
}
...
Will this work for the above situation?
I make a Ouputstream version without any dependency to 3rd party libs for easier re-use. You can use this 2 wrapper class to get the request & response body easily.
But anyway, I have to use a filter to do this instead of interceptor. Because as #user1323865 mentioned, in spring 4, the processedRequest is used in both interceptor and handler, so you cannot use these methods for interceptor.
Also you can find some help in this link if you're using Writer version instead.
Capture and log the response body
public class BufferedRequestWrapper extends HttpServletRequestWrapper
{
private static final class BufferedServletInputStream extends ServletInputStream
{
private ByteArrayInputStream bais;
public BufferedServletInputStream(ByteArrayInputStream bais)
{
this.bais = bais;
}
#Override
public int available()
{
return this.bais.available();
}
#Override
public int read()
{
return this.bais.read();
}
#Override
public int read(byte[] buf, int off, int len)
{
return this.bais.read(buf, off, len);
}
}
private byte[] mBodyBuffer;
public BufferedRequestWrapper(HttpServletRequest request) throws IOException
{
super(request);
InputStream in = request.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = in.read(buffer)) > 0)
{
baos.write(buffer, 0, bytesRead);
}
mBodyBuffer = baos.toByteArray();
}
public String getRequestBody()
{
return new String(mBodyBuffer, Charset.forName("UTF-8"));
}
#Override
public BufferedReader getReader() throws IOException
{
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
#Override
public ServletInputStream getInputStream()
{
ByteArrayInputStream in = new ByteArrayInputStream(mBodyBuffer);
return new BufferedServletInputStream(in);
}
}
public class BufferedResponseWrapper extends HttpServletResponseWrapper
{
private TeeServletOutputStream mTeeOutputStream;
private static class TeeOutputStream extends OutputStream
{
private OutputStream mChainStream;
private OutputStream mTeeStream;
public TeeOutputStream(OutputStream chainStream, OutputStream teeStream)
{
mChainStream = chainStream;
mTeeStream = teeStream;
}
#Override
public void write(int b) throws IOException
{
mChainStream.write(b);
mTeeStream.write(b);
mTeeStream.flush();
}
#Override
public void close() throws IOException
{
flush();
mChainStream.close();
mTeeStream.close();
}
#Override
public void flush() throws IOException
{
mChainStream.close();
}
}
public class TeeServletOutputStream extends ServletOutputStream
{
private final TeeOutputStream targetStream;
public TeeServletOutputStream(OutputStream one, OutputStream two)
{
targetStream = new TeeOutputStream(one, two);
}
#Override
public void write(int b) throws IOException
{
this.targetStream.write(b);
}
#Override
public void flush() throws IOException
{
super.flush();
this.targetStream.flush();
}
#Override
public void close() throws IOException
{
super.close();
this.targetStream.close();
}
}
private ByteArrayOutputStream mByteArrayOutputStream;
public BufferedResponseWrapper(HttpServletResponse response) throws IOException
{
super(response);
mByteArrayOutputStream = new ByteArrayOutputStream();
mTeeOutputStream = new TeeServletOutputStream(super.getResponse().getOutputStream(), mByteArrayOutputStream);
}
#Override
public PrintWriter getWriter() throws IOException
{
return super.getResponse().getWriter();
}
#Override
public ServletOutputStream getOutputStream() throws IOException
{
return mTeeOutputStream;
}
public String getResponseBody()
{
return mByteArrayOutputStream.toString();
}
}
One simple way to do this would be to get the request body as String and then parse as a Java object. You can use this String then as you want.
So in your example:
#RequestMapping(method = RequestMethod.POST, consumes="application/json", produces="application/json", value = "employee")
#ResponseBody
public String updateEntity(#RequestBody String empAsString) {
// Do whatever with the json as String
System.out.println(empAsString);
// Transform it into the Java Object you want
ObjectMapper mapper = new ObjectMapper();
Employee emp = mapper.readValue(empAsString, Employee.class);
// Do some DB Stuff. Anyway, the control flow does not reach this place.
return "Employee " + emp.getName() + " updated successfully!";
}
As a note, if you need it as a list you can use:
List<Employee> eventsList =
mapper.readValue(jsonInString, mapper.getTypeFactory().constructCollectionType(List.class, Employee.class));
You need to implement the requestWrapper as follows:
public class DocVerificationRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public DocVerificationRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
#Override
public boolean isFinished() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
#Override
public void setReadListener(ReadListener listener) {
// TODO Auto-generated method stub
}
};
return servletInputStream;
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
}
and then inside the chain.doFilter method of filter class pass the requestWrapper object instead of the request object as follows:
#Override
public void doFilter(ServletRequest arg0, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
logger.info("checking token in filter");
HttpServletRequest request = (HttpServletRequest) arg0;
DocVerificationRequestWrapper myRequestWrapper = new DocVerificationRequestWrapper((HttpServletRequest) request);
String body = myRequestWrapper.getBody();
logger.info("body = "+body);
Token token = null;
try {
JSONObject jsonObj = new JSONObject(body);
JSONObject tokenObj = (JSONObject) jsonObj.get("token");
Gson gson = new Gson();
token = gson.fromJson(tokenObj.toString(), Token.class);
if(null != token) {
if(userVerificationService==null){
ServletContext servletContext = request.getServletContext();
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
userVerificationService = webApplicationContext.getBean(UserVerificationService.class);
}
String verStatus = userVerificationService.verifyUser(token);
logger.info("verStatus = "+verStatus);
if(verStatus != null && verStatus.equalsIgnoreCase("success")) {
chain.doFilter(myRequestWrapper, response); //here replacing request with requestWrapper
}else
logger.error("Invalid token");
}else {
logger.error("token missing.");
}
} catch (JSONException e) {
logger.error("exception in authetication filter " + e);
}
}
Thus solving the IOStream closed exception.
For getting data from Body you can try to read and recreate InputStream in RequestBodyAdviceAdapter:
#ControllerAdvice
public class CustomRequestBodyAdviceAdapter extends RequestBodyAdviceAdapter {
#Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
String body = IOUtils.toString(inputMessage.getBody(), UTF_8.name());
HttpInputMessage myMessage = new HttpInputMessage(){
#Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(body.getBytes());
}
#Override
public HttpHeaders getHeaders() {
return inputMessage.getHeaders();
}
};
System.out.println("Data from Body: " + body);
return super.beforeBodyRead(myMessage, parameter, targetType, converterType);
}
#Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
System.out.println("Data from Body is empty");
return super.handleEmptyBody(body, inputMessage, parameter, targetType, converterType);
}
#Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
#Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
}
You can simply use :
import org.apache.commons.io.IOUtils;
import java.nio.charset.Charset;
String requestBody = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8").toString());
In my experiences,just develop as follows:
Using the filter in order to wrapper ServletRequest,then you can repeatly use getting request input stream.