I'd like to invoke IBM Bluemix service (say Text to Speech) from my Java code.
I've managed to get service credentials and URL but how can I invoke it after?
I've seen some example where people have used similar to below code but wondering how it works for a Text to Speech where it outputs a wav stream.
String profileString = ex.execute(profileRequest)
.handleResponse(new ResponseHandler<String>() {
#Override
public String handleResponse(HttpResponse r)
throws ClientProtocolException, IOException {
}
}
Can any one suggest on priority please?
The link below has a Java code example of how to use the Watson text-to-speech service.
https://github.com/watson-developer-cloud/text-to-speech-java
You should be looking for something like this from the DemoServlet.java class:
#Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
if (req.getParameter("text") == null || req.getParameter("voice") == null) {
req.getRequestDispatcher("/index.jsp").forward(req, resp);
} else {
boolean download = false;
if (req.getParameter("download") != null && req.getParameter("download").equalsIgnoreCase("true")) {
download = true;
}
req.setCharacterEncoding("UTF-8");
try {
String queryStr = req.getQueryString();
String url = baseURL + "/v1/synthesize";
if (queryStr != null) {
url += "?" + queryStr;
}
URI uri = new URI(url).normalize();
Request newReq = Request.Get(uri);
newReq.addHeader("Accept", "audio/ogg; codecs=opus");
Executor executor = Executor.newInstance().auth(username, password);
Response response = executor.execute(newReq);
if (download)
{
resp.setHeader("content-disposition", "attachment; filename=transcript.ogg");
}
ServletOutputStream servletOutputStream = resp.getOutputStream();
response.returnResponse().getEntity()
.writeTo(servletOutputStream);
servletOutputStream.flush();
servletOutputStream.close();
} catch (Exception e) {
// Log something and return an error message
logger.log(Level.SEVERE, "got error: " + e.getMessage(), e);
resp.setStatus(HttpStatus.SC_BAD_GATEWAY);
}
}
}
Finally, the link below has instructions on how to create a Java war file and deploy to Bluemix:
https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/getting_started/gs-full-java.shtml
Related
I want to print a document in my java web application using servlet and i clear report info to avoid download resume(SecurityContext.cleanReportInfo()).
everything is ok when you don't have IDM in your system but when IDM is running it sends 2 request instead 1 and everything goes wrong by redirecting to /403 like the code below .
PrintReportServlet
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ReportDto reportInfo = SecurityContext.getReportInfo();
if (reportInfo != null) {
ServletOutputStream outputStream = response.getOutputStream();
try {
generateHeaders(response, reportInfo);
generateContents(outputStream, reportInfo);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Error occurred during print report, nested error message: {0}", e.getMessage());
} finally {
outputStream.flush();
outputStream.close();
SecurityContext.cleanReportInfo();
}
} else {
response.sendRedirect(request.getContextPath() + "/403");
}
}
SecurityContext.java
public static void cleanReportInfo() {
SecurityContext.getCurrentSession().setAttribute("Report_Info", null);
}
errorreportController.js
$scope.printErrorList = function () {
errorReportService.printErrorList(function () {
window.open(contextPath + "/PrintReport");
});
};
ErrorReportController.java
#RequestMapping(value = "/printError", method = RequestMethod.GET)
#ResponseBody
public String printError() {
ReportDto reportDto = errorReportService.getReportInfo();
SecurityContext.setReportInfo(reportDto);
return success();
}
ErrorReportServiceImpl
public ReportDto getReportInfo() {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("jalaliDate", DateUtil.convertToJalali(new Date()).toStringBySlash());
parameters.put("alahImagePath", ReportUtil.getImagesPath() + File.separator + "alah.png");
parameters.put("sepahImagePath", ReportUtil.getImagesPath() + File.separator + "sepah.png");
parameters.put("reporter", SecurityContext.getCurrentUserName());
parameters.put("classify", "Normal");
parameters.put("userId",SecurityContext.getCurrentUserId());
ReportDto reportDto = new ReportDto(
ReportNames.ErrorReport, DataItems.Report_Type_PDF,
"error",
parameters);
return reportDto;
}
I'm working on a web app (Java/JSP) and part of it, is to allow users to download the requested file only "Once". The problem that when they hit "Download" button, they will be asked to save/open or cancel the file and whatever they respond the file will be marked as downloaded and the user won't be able to download it again.
I'm trying to figure out a way to not count the file as downloaded when the user respond with "Cancel" and to check if really the user downloaded the file completely.
Here is the Java Part:
#WebServlet("/download")
public class download extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final int DEFAULT_BUFFER_SIZE = 10240;
/**
* #see HttpServlet#HttpServlet()
*/
public download() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Class.forName("org.sqlite.JDBC");
Connection c = DriverManager.getConnection("jdbc:sqlite:C:\\sqlite\\mascapp.db");
c.setAutoCommit(false);
Cookie[] cookies = request.getCookies();
if(request.getSession().getAttribute("aeid") == null || request.getSession().getAttribute("uid") == null)
{
response.sendRedirect("/index.jsp");
}
int ae_num = Integer.parseInt(request.getSession().getAttribute("aeid").toString());
String sql = "SELECT file, filename FROM reports INNER JOIN download USING(tipid) WHERE reports.tipid = ?"+
"AND download.ts_" + ae_num+ " = 0;";
PreparedStatement stmt = c.prepareStatement(sql);
String tipNum = request.getParameter("tipid");
if (tipNum != null) {
stmt.setString(1, tipNum);
//stmt.setString(2, tipNum);
ResultSet res = stmt.executeQuery();
BufferedInputStream fileBlob = null;
String filename = "";
while (res.next()) {
fileBlob = new BufferedInputStream(res.getBinaryStream("file"), DEFAULT_BUFFER_SIZE);
filename = res.getString("filename");
}
if (fileBlob != null) {
System.out.println(filename);
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
BufferedOutputStream output = new BufferedOutputStream(response.getOutputStream(),
DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = fileBlob.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.close();
fileBlob.close();
Date now = new Date();
sql = "UPDATE download SET ts_" + ae_num + " = " + now.getTime() + " WHERE tipid = ?;";
System.out.println(sql);
stmt = c.prepareStatement(sql);
stmt.setString(1, tipNum);
stmt.executeUpdate();
stmt.close();
c.commit();
c.close();
}
else
{
c.close();
response.sendRedirect("/MASC/formdownloaded.jsp");
}
}
else
{
response.getWriter().append("<html><body><h1>Error: no param</h1></body></html>");
c.close();
}
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
Any solution or suggestion?! Thank you in advance.
Check this page: http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/ (this link doesn't work sometimes, if you have some problems with it here is a link to github: https://github.com/johnculviner/jquery.fileDownload ).
It looks like the best you can do here is to make sure that download was started by checking on client side special cookie sent back from server with downloading file stream. For that you have to add Cookie into servlet response like in this thread:
Set cookie only after file download complete.
So at the end of doGet method in your servlet you should have something like:
Cookie fileDwnld = new Cookie("fileDownload", "true");
fileDwnld.setPath("/");
response.addCookie(fileDwnld);
And here is client side code:
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="jquery.fileDownload.js"></script>
<script>
$(document).ready(function() {
$("#btnSubmit").click(function(){
$.fileDownload('path/to/servlet')
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); });
});
});
The answer is don't do that. Those dialogs are there for good reasons, some of them involving security.
What you want to do instead depends on why you only want the user to download the file once. Downloads can fail for all sorts of reasons, so what are you going to do if the user loses their connection in the middle of the download?
I don't have a proper answer, but I do know that the "attachment;" in the header forces the browser to "download" the file, compared to "open it", if you understand what I mean. Try removing that header and see if you get the desired effect.
I am trying to cache images in an android app with this solution Android image caching. I have already implemented a specific ResponseCache and overriden the get and put methods.
Despite that, images are not properly cached. When I debug I can see that the put method of my ResponseCache implementation is never called. My get method is properly called each time a request is made but never is the put method. Nothing is never cached so it can't retrieve any file...
My request use HTTPS so i was wondering if caching the response was allowed or if i'll have to deal with requesting the server every time I want to display my images.
Here is the code :
public class ImageResponseCache extends ResponseCache {
File cacheDir;
public ImageResponseCache(File cacheDir) {
super();
this.cacheDir = cacheDir;
}
#Override
public CacheResponse get(URI uri, String s,
Map<String, List<String>> headers) throws IOException {
final File file = new File(cacheDir, escape(uri.getPath()));
if (file.exists()) {
return new CacheResponse() {
#Override
public Map<String, List<String>> getHeaders()
throws IOException {
return null;
}
#Override
public InputStream getBody() throws IOException {
return new FileInputStream(file);
}
};
} else {
return null;
}
}
#Override
public CacheRequest put(URI uri, URLConnection urlConnection)
throws IOException {
Log.i("Image Response", "PUT");
final File file = new File(cacheDir, escape(urlConnection.getURL()
.getPath()));
return new CacheRequest() {
#Override
public OutputStream getBody() throws IOException {
return new FileOutputStream(file);
}
#Override
public void abort() {
file.delete();
}
};
}
private String escape(String url) {
return url.replace("/", "-").replace(".", "-");
}
}
Here is the function that request my images in an adapter:
private Bitmap requestImage(String file) {
Bitmap bm = null;
Log.d(TAG, "path: " + file);
URL url = null;
HttpURLConnection http = null;
try {
url = new URL(file);
if (url.getProtocol().toLowerCase().equals("https")) {
NetworkUtils.trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url
.openConnection();
https.setHostnameVerifier(NetworkUtils.DO_NOT_VERIFY);
http = https;
} else {
http = (HttpURLConnection) url.openConnection();
}
http.setUseCaches(true);
ResponseCache.setDefault(new ImageResponseCache(
ImageAdapter.this.mContext.getCacheDir()));
http.setRequestProperty(
"Authorization",
"Basic "
+ Base64.encodeToString(
(Constants.USER + ":" + Constants.PASSWORD)
.getBytes(), Base64.NO_WRAP));
http.setConnectTimeout(Constants.TIME_OUT);
bm = BitmapFactory.decodeStream((InputStream) http.getContent());
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
return bm;
}
Does anyone know what could be wrong?
I am trying to get the whole body from the HttpServletRequest object.
The code I am following looks like this:
if ( request.getMethod().equals("POST") )
{
StringBuffer sb = new StringBuffer();
BufferedReader bufferedReader = null;
String content = "";
try {
//InputStream inputStream = request.getInputStream();
//inputStream.available();
//if (inputStream != null) {
bufferedReader = request.getReader() ; //new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead;
while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) {
sb.append(charBuffer, 0, bytesRead);
}
//} else {
// sb.append("");
//}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
test = sb.toString();
}
and I am testing the functionality with curl and wget as follows:
curl --header "MD5: abcd" -F "fileupload=#filename.txt http://localhost:8080/abcd.html"
wget --header="MD5: abcd" --post-data='{"imei":"351553012623446","hni":"310150","wdp":false}' http://localhost:8080/abcd.html"
But the while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) does not return anything, and so I get nothing appended on StringBuffer.
In Java 8, you can do it in a simpler and clean way :
if ("POST".equalsIgnoreCase(request.getMethod()))
{
test = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}
Easy way with commons-io.
IOUtils.toString(request.getReader());
https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/IOUtils.html
Be aware, that your code is quite noisy.
I know the thread is old, but a lot of people will read it anyway.
You could do the same thing using the guava library with:
if ("POST".equalsIgnoreCase(request.getMethod())) {
test = CharStreams.toString(request.getReader());
}
If all you want is the POST request body, you could use a method like this:
static String extractPostRequestBody(HttpServletRequest request) throws IOException {
if ("POST".equalsIgnoreCase(request.getMethod())) {
Scanner s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
return "";
}
Credit to: https://stackoverflow.com/a/5445161/1389219
This works for both GET and POST:
#Context
private HttpServletRequest httpRequest;
private void printRequest(HttpServletRequest httpRequest) {
System.out.println(" \n\n Headers");
Enumeration headerNames = httpRequest.getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = (String)headerNames.nextElement();
System.out.println(headerName + " = " + httpRequest.getHeader(headerName));
}
System.out.println("\n\nParameters");
Enumeration params = httpRequest.getParameterNames();
while(params.hasMoreElements()){
String paramName = (String)params.nextElement();
System.out.println(paramName + " = " + httpRequest.getParameter(paramName));
}
System.out.println("\n\n Row data");
System.out.println(extractPostRequestBody(httpRequest));
}
static String extractPostRequestBody(HttpServletRequest request) {
if ("POST".equalsIgnoreCase(request.getMethod())) {
Scanner s = null;
try {
s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
} catch (IOException e) {
e.printStackTrace();
}
return s.hasNext() ? s.next() : "";
}
return "";
}
If the request body is empty, then it simply means that it's already been consumed beforehand. For example, by a request.getParameter(), getParameterValues() or getParameterMap() call. Just remove the lines doing those calls from your code.
This will work for all HTTP method.
public class HttpRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public HttpRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = IOUtils.toString(request.getReader());
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getBody().getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
#Override
public boolean isFinished() {
return false;
}
#Override
public boolean isReady() {
return false;
}
#Override
public void setReadListener(ReadListener listener) {
}
};
return servletInputStream;
}
public String getBody() {
return this.body;
}
}
Easiest way I could think of:
request.getReader().lines().reduce("",String::concat)
However, this will be one long string which you will have to parse. IF you send a username of tim and a password of 12345. The output of the code above would look like this:
{ "username":"tim", "password": "12345"}
Please be aware
Please be aware that with the reduce() method we are performing a Mutable Reduction which does a great deal of string copying and has a runtime of O(N^2) with N being the number of characters. Please check the Mutable Reduction documentation if you need a more performant result.
I resolved that situation in this way. I created a util method that return a object extracted from request body, using the readValue method of ObjectMapper that is capable of receiving a Reader.
public static <T> T getBody(ResourceRequest request, Class<T> class) {
T objectFromBody = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
HttpServletRequest httpServletRequest = PortalUtil.getHttpServletRequest(request);
objectFromBody = objectMapper.readValue(httpServletRequest.getReader(), class);
} catch (IOException ex) {
log.error("Error message", ex);
}
return objectFromBody;
}
I personnally use this code (on a dev server, not in production). Seems to work. The main difficulty is that once you read the request body, it will be lost and not transferred to the app. So you have to "cache" it first.
/* Export this filter as a jar and place it under directory ".../tomcat/lib" on your Tomcat server/
In the lib directory, also place the dependencies you need
(ex. org.apache.commons.io => commons-io-2.8.0.jar)
Once this is done, in order to activate the filter, on the Tomcat server:
o in .../tomcat/conf/server.xml, add:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" [%{postdata}r] %s %b"/>
=> the server will log the "postdata" attribute we generate in the Java code.
o in .../tomcat/conf/web.xml, add:
<filter>
<filter-name>post-data-dumper-filter</filter-name>
<filter-class>filters.PostDataDumperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>post-data-dumper-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Once you've done this, restart your tomcat server. You will get extra infos in file "localhost_access_log.<date>.txt"
*/
package filters;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.stream.Collectors;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
private ByteArrayOutputStream cachedBytes;
public MultiReadHttpServletRequest(HttpServletRequest request) {
super(request);
}
#Override
public ServletInputStream getInputStream() throws IOException {
if (cachedBytes == null)
cacheInputStream();
return new CachedServletInputStream();
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
private void cacheInputStream() throws IOException {
/* Cache the inputstream in order to read it multiple times.
*/
cachedBytes = new ByteArrayOutputStream();
IOUtils.copy(super.getInputStream(), cachedBytes);
}
/* An input stream which reads the cached request body */
public class CachedServletInputStream extends ServletInputStream {
private ByteArrayInputStream input;
public CachedServletInputStream() {
/* create a new input stream from the cached request body */
input = new ByteArrayInputStream(cachedBytes.toByteArray());
}
//---------------------
#Override
public int read() throws IOException {
return input.read();
}
#Override
public boolean isFinished() {
return input.available() == 0;
}
#Override
public boolean isReady() {
return true;
}
//---------------------
#Override
public void setReadListener(ReadListener arg0) {
// TODO Auto-generated method stub
// Ex. : throw new RuntimeException("Not implemented");
}
}
}
public final class PostDataDumperFilter implements Filter {
private FilterConfig filterConfig = null;
public void destroy() {
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (filterConfig == null)
return;
StringBuffer output = new StringBuffer();
output.append("PostDataDumperFilter-");
/* Wrap the request in order to be able to read its body multiple times */
MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest((HttpServletRequest) request);
// TODO : test the method in order not to log the body when receiving GET/DELETE requests ?
// I finally leave it "as it", since I've seen GET requests containing bodies (hell...).
output.append("Content-type=" + multiReadRequest.getContentType());
output.append(" - HTTP Method=" + multiReadRequest.getMethod());
output.append(" - REQUEST BODY = " + multiReadRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator())));
// Log the request parameters:
Enumeration names = multiReadRequest.getParameterNames();
if (names.hasMoreElements()) {
output.append("- REQUEST PARAMS = ");
}
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
output.append(name + "=");
String values[] = multiReadRequest.getParameterValues(name);
for (int i = 0; i < values.length; i++) {
if (i > 0) output.append("' ");
output.append(values[i]);
}
if (names.hasMoreElements()) output.append("&");
}
multiReadRequest.setAttribute("postdata", output);
chain.doFilter(multiReadRequest, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
}
I'm trying to post 2 fields, id and data, to a servlet using HttpClient.
The problem is that if the length of the data field is less than 1MB or so, the servlet will get what I posted. But if the length of the data field is larger than 1MB or so, the servlet will receive null for all fields. What am I missing here? Thanks.
Here's the sample data that I post to the servlet:
id=12312123123123
data=the content of a file that is base-64 encoded
Here's the method that I use to post data to the servlet.
private byte[] post(String aUrl,
Map<String,String> aParams,
String aCharsetEnc,
int aMaxWaitMs) throws Exception
{
PostMethod post = null;
try
{
HttpClient client = new HttpClient();
post = new PostMethod(aUrl);
post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=" + aCharsetEnc);
for (String key : aParams.keySet())
{
post.addParameter(key, aParams.get(key));
}
final int code = client.executeMethod(post);
if (code == HttpStatus.SC_NO_CONTENT || code == HttpStatus.SC_NOT_FOUND)
{
return null;
}
else if (code != HttpStatus.SC_OK)
{
throw new HttpException("Error code " + code + " encountered.");
}
InputStream stream = post.getResponseBodyAsStream();
if (stream != null)
{
return BlobHelper.readBytes(stream);
}
return null;
}
finally
{
if (post != null)
{
post.releaseConnection();
}
}
}
Here's the method of the servlet.
public void doPost(HttpServletRequest aReq, HttpServletResponse aResp)
throws ServletException, IOException
{
setNoCache(aResp);
aResp.setContentType("text/plain");
try
{
final String id = aReq.getParameter(PARAM_ID);
final String dataStr = aReq.getParameter(PARAM_DATA);
if (log().isDebugEnabled())
{
log().debug("id=" + id);
log().debug("data=" + dataStr);
}
}
catch (Exception e)
{
}
}
Usually servlet containers have a maximum post size parameter.
For Tomcat you can follow the steps documented here(they should be similar for other appservers) -
Is there a max size for POST parameter content?