I used a jersey server and I want that a endpoint redirect to the download of a file depending on parameters.
I have difficulties with the function below :
#GET
#Path("/get/{id}/{chunk}")
public Response getDescription(#PathParam("id") String id, #PathParam("chunk") String chunk) {
{
StreamingOutput fileStream = new StreamingOutput()
{
#Override
public void write(java.io.OutputStream output, String id) throws IOException, WebApplicationException
{
try
{
if (Objects.equals(chunk, new String("init"))) {
java.nio.file.Path path = Paths.get("src/main/uploads/example/frame_init.pdf");
}
else {
java.nio.file.Path path = Paths.get("src/main/uploads/example/"+ id +".pdf");
}
byte[] data = Files.readAllBytes(path);
output.write(data);
output.flush();
}
catch (Exception e)
{
throw new WebApplicationException("File Not Found !!");
}
}
};
return Response
.ok(fileStream, MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition","attachment; filename = myfile.pdf")
.build();
}
I have a problem with passing parameters to the function write. I have my parameters id and chunk by the endpoint but I can't use it in the write method because it implements StreamingOutput().
How I can handle it ? Thank you
For java, final keyword should solve your problem.
As updated code;
#GET
#Path("/get/{id}/{chunk}")
public Response getDescription(#PathParam("id") final String id, #PathParam("chunk") final String chunk) {
{
StreamingOutput fileStream = new StreamingOutput()
{
#Override
public void write(java.io.OutputStream output, String id2) throws IOException, WebApplicationException
{
try
{
if (Objects.equals(chunk, new String("init"))) {
java.nio.file.Path path = Paths.get("src/main/uploads/example/frame_init.pdf");
}
else {
java.nio.file.Path path = Paths.get("src/main/uploads/example/"+ id2 +".pdf");
}
byte[] data = Files.readAllBytes(path);
output.write(data);
output.flush();
}
catch (Exception e)
{
throw new WebApplicationException("File Not Found !!");
}
}
};
return Response
.ok(fileStream, MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition","attachment; filename = myfile.pdf")
.build();
}
Related
I'm sending a SOAP message using apache cxf and what I want is to get both request and response payloads after the call is finished. Currently I'm using two interceptors and put payloads into messages' context like that message.getExchange().put(ExchangeContextEnum.RESPONSE_PAYLOAD.toString(), new String(payload, Charset.forName(StandardCharsets.UTF_8.name())));.
I don't want to process them right away in the interceptor itself because I need requests and responses for the series of calls. Also, I'd like to avoid making any kind of storage for the sake of simplicity and not having to deal with possible concurrency issues.
Can I get those values after the call is finished or the context is completely lost at this point?
Some code:
webService.call(object)
//here i'd like to get payloads
Interceptor for response:
public class LogInInterceptor extends AbstractPhaseInterceptor<Message> {
public LogInInterceptor() {
super(Phase.RECEIVE);
}
#Override
public void handleMessage(Message message) throws Fault {
InputStream in = message.getContent(InputStream.class);
byte payload[] = new byte[0];
try {
payload = IOUtils.readBytesFromStream(in);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayInputStream bin = new ByteArrayInputStream(payload);
message.setContent(InputStream.class, bin);
message.getExchange().put(ExchangeContextEnum.RESPONSE_PAYLOAD.toString(), new String(payload, Charset.forName(StandardCharsets.UTF_8.name())));
}
}
Interceptor for request:
public class WSSLogOutInterceptor extends AbstractSoapInterceptor {
public WSSLogOutInterceptor() {
super(Phase.USER_PROTOCOL);
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
SOAPMessage messageContent = message.getContent(SOAPMessage.class);
messageContent.writeTo(baos);
message.getExchange().put(ExchangeContextEnum.REQUEST_PAYLOAD.toString(), baos.toString());
} catch (SOAPException | IOException e) {
throw new Fault(e);
}
}
}
I ended up with the following solution:
Instead of putting values in message's exchange i simply do message.put(key, value) in the interceptor. To get those values after the call you
need to get response context like that (String) ((BindingProvider) webService).getResponseContext().get(key) where key is the same value you used before to put payload in the message. Now here's the problem - you won't find values that you put in the outgoing chain in response context. You can use simple workaround and put value in the exchange of the message and then, in the ingoing chain get it and put it into message. Pay attention to the phase I used (POST_PROTOCOL), it'd helpful if you use WSS.
Here's the code:
public class LoggingOutPayloadInterceptor extends AbstractSoapInterceptor {
public static final String OUT_PAYLOAD_KEY = "use.your.package.name.OUT_PAYLOAD_KEY";
public LoggingOutPayloadInterceptor() {
super(Phase.POST_PROTOCOL);
}
#Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
Document document = soapMessage.getContent(SOAPMessage.class).getSOAPPart();
StringWriter stringWriter = new StringWriter();
try {
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(stringWriter));
} catch (TransformerException e) {
e.printStackTrace();
}
soapMessage.getExchange().put(OUT_PAYLOAD_KEY, stringWriter.toString());
}
}
public class LoggingInPayloadInterceptor extends AbstractSoapInterceptor {
public static final String IN_PAYLOAD_KEY = "use.your.package.name.IN_PAYLOAD";
public LoggingInPayloadInterceptor() {
super(Phase.POST_PROTOCOL);
addAfter(SAAJInInterceptor.class.getName());
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
Document document = message.getContent(SOAPMessage.class).getSOAPPart();
StringWriter stringWriter = new StringWriter();
try {
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(stringWriter));
} catch (TransformerException e) {
e.printStackTrace();
}
message.put(IN_PAYLOAD_KEY, stringWriter.toString());
message.put(LoggingOutPayloadInterceptor.OUT_PAYLOAD_KEY, message.getExchange().get(LoggingOutPayloadInterceptor.OUT_PAYLOAD_KEY));
}
}
webService.call(...);
String inPayload = (String)((BindingProvider)webService).getResponseContext().get(LoggingInPayloadInterceptor.IN_PAYLOAD_KEY);
String outPayload = (String) ((BindingProvider) webService).getResponseContext().get(LoggingOutPayloadInterceptor.OUT_PAYLOAD_KEY);
What should be the value of or initialize InputStreamSupplier?
I was trying to zip all the files in a directory and that should be fast.
So multi threading is the option i'm going for.
public class ScatterSample {
ParallelScatterZipCreator scatterZipCreator = new ParallelScatterZipCreator();
ScatterZipOutputStream dirs = ScatterZipOutputStream.fileBased(File.createTempFile("scatter-dirs", "tmp"));
public ScatterSample() throws IOException {
}
public void addEntry(ZipArchiveEntry zipArchiveEntry, InputStreamSupplier streamSupplier) throws IOException {
if (zipArchiveEntry.isDirectory() && !zipArchiveEntry.isUnixSymlink())
dirs.addArchiveEntry(ZipArchiveEntryRequest.createZipArchiveEntryRequest(zipArchiveEntry, streamSupplier));
else
scatterZipCreator.addArchiveEntry( zipArchiveEntry, streamSupplier);
}
public void writeTo(ZipArchiveOutputStream zipArchiveOutputStream)
throws IOException, ExecutionException, InterruptedException {
dirs.writeTo(zipArchiveOutputStream);
dirs.close();
scatterZipCreator.writeTo(zipArchiveOutputStream);
}
}
FirstMain Class:
public class FirstMain {
public FirstMain() {
// TODO Auto-generated constructor stub
}
public static void compressFolder(String sourceFolder, String absoluteZipfilepath)
{
try
{
ScatterSample scatterSample=new ScatterSample();
File srcFolder = new File(sourceFolder);
if(srcFolder != null && srcFolder.isDirectory())
{
Iterator<File> i = FileUtils.iterateFiles(srcFolder, new String []{"pdf"}, true);
File zipFile = new File(absoluteZipfilepath);
OutputStream outputStream = new FileOutputStream(zipFile);
ZipArchiveOutputStream zipArchiveOutputStream= new ZipArchiveOutputStream(outputStream);
int srcFolderLength = srcFolder.getAbsolutePath().length() + 1; // +1 to remove the last file separator
while(i.hasNext())
{
File file = i.next();
String relativePath = file.getAbsolutePath().substring(srcFolderLength);
InputStreamSupplier streamSupplier=new InputStreamSupplier(){
#Override
public InputStream get() {
// TODO Auto-generated method stub
return null;
}
};
ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(relativePath);
scatterSample.addEntry(zipArchiveEntry, streamSupplier);
}
scatterSample.writeTo(zipArchiveOutputStream);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main( String[] args )
{
compressFolder("C:\\Users\\akatm\\Desktop\\Stuff\\zipdata\\Newtry\\","C:/Users/akatm/Desktop/Stuff/Newtry.zip");
}
}
The get() method must return an InputStream to the file.
You could define an internal class as the following:
static class FileInputStreamSupplier implements InputStreamSupplier {
private Path sourceFile;
FileInputStreamSupplier(Path sourceFile) {
this.sourceFile = sourceFile;
}
#Override
public InputStream get() {
InputStream is = null;
try {
is = Files.newInputStream(sourceFile);
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
}
That you could then invoke as:
scatterSample.addEntry(zipArchiveEntry, new FileInputStreamSupplier(file.toPath());
You need to set the compress method in the ZipEntry
ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(relativePath);
zipArchiveEntry.setMethod(ZipArchiveEntry.STORED);
scatterSample.addEntry(zipArchiveEntry, streamSupplier);
if you don't set the compress method, the method throws an exception.
I'm reading the source code of class BufferingClientHttpRequestWrapper:
final class BufferingClientHttpRequestWrapper extends AbstractBufferingClientHttpRequest {
private final ClientHttpRequest request;
BufferingClientHttpRequestWrapper(ClientHttpRequest request) {
Assert.notNull(request, "'request' must not be null");
this.request = request;
}
public HttpMethod getMethod() {
return this.request.getMethod();
}
public URI getURI() {
return this.request.getURI();
}
#Override
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
OutputStream body = this.request.getBody();
this.request.getHeaders().putAll(headers);
FileCopyUtils.copy(bufferedOutput, body);
ClientHttpResponse response = this.request.execute();
return new BufferingClientHttpResponseWrapper(response);
}
}
In the overrided method executeInternal,
OutputStream body = this.request.getBody();
this.request.getHeaders().putAll(headers);
FileCopyUtils.copy(bufferedOutput, body);
ClientHttpResponse response = this.request.execute();
I noticed that this.request.getBody() comes before this.request.getHeaders().putAll(headers), which may be a bug causing the passed in headers never be written. Say, if the wrapped request is an instance of SimpleStreamingClientHttpRequest, the related source code of SimpleStreamingClientHttpRequest is as folows:
#Override
protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException {
if (this.body == null) {
int contentLength = (int) headers.getContentLength();
if (contentLength >= 0 && !olderThanFroyo) {
this.connection.setFixedLengthStreamingMode(contentLength);
} else {
this.connection.setChunkedStreamingMode(this.chunkSize);
}
writeHeaders(headers);
this.connection.connect();
this.body = this.connection.getOutputStream();
}
return new NonClosingOutputStream(this.body);
}
#Override
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
try {
if (this.body != null) {
this.body.close();
} else {
writeHeaders(headers);
this.connection.connect();
}
} catch (IOException ex) {
// ignore
}
return new SimpleClientHttpResponse(this.connection);
}
From above code snippet, We can tell that once getBody() is called(which calls getBodyInternal()), the headers was written to the connection(HttpUrlConnection) and calling execute()(which calls executeInternal()) will NOT write the headers.(cos this.body will not be null). In this case, let's return to BufferingClientHttpRequestWrapper's implementation:
OutputStream body = this.request.getBody();
this.request.getHeaders().putAll(headers);
FileCopyUtils.copy(bufferedOutput, body);
ClientHttpResponse response = this.request.execute();
The first line will cause the old headers be written, and the second line trying to put new headers entries is in vain(cos the fouth line will never write headers, as explained above).
Is this a BUG or am I wrong? (Anyway, I'll try it out by practice when I'm in no hurry...)
I have a form and I want to serve an AbstractResource by calling
getRequestCycle().scheduleRequestHandlerAfterCurrent(target);
Where target has to be an implementation of IRequestHandler.
I want to pass the following AbstractResource object.
public class ExcelResponseResource extends AbstractResource {
#Override
protected ResourceResponse newResourceResponse(Attributes attributes) {
ResourceResponse resourceResponse = new ResourceResponse();
resourceResponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
resourceResponse.setTextEncoding("utf-8");
resourceResponse.setFileName("SomeExport.xlsx");
resourceResponse.setWriteCallback(new WriteCallback() {
#Override
public void writeData(Attributes attributes) {
try {
SomeExport export = new SomeExport(arguments);
byte[] byteArray = ((ByteArrayOutputStream)export.getOutputStream()).toByteArray();
attributes.getResponse().write(byteArray);
} catch (Exception e) {
log.error("Something went wrong during Excel generation!", e);
}
}
});
resourceResponse.disableCaching();
return resourceResponse;
}
}
I want to know how i can put this beast into a ResourceStreamRequestHandler or something similar.
Thanks in advance!
Changed the AbstractResource to an AbstractResourceStream and now it works like a charm.
ExcelResourceStream stream = new ExcelResourceStream();
ResourceStreamRequestHandler requestHandler = new ResourceStreamRequestHandler(stream);
getRequestCycle().scheduleRequestHandlerAfterCurrent(requestHandler);
And the ExcelResourceStream looks like this:
public class ExcelResourceStream extends AbstractResourceStream {
private ByteArrayInputStream inputStream;
#Override
public String getContentType() {
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
#Override
public Bytes length() {
return Bytes.bytes(inputStream.available());
}
#Override
public InputStream getInputStream() throws ResourceStreamNotFoundException {
if (inputStream == null) {
SomeExport export = new SomeExport();
try {
byte[] byteArray = ((ByteArrayOutputStream)export.getOutputStream()).toByteArray();
inputStream = new ByteArrayInputStream(byteArray);
} catch (IOException ioe) {
// STUB
}
}
return inputStream;
}
#Override
public void close() throws IOException {
if (inputStream != null) {
inputStream.close();
}
}
}
Does anyone know where to find a little how to on using dbpedia spotlight in java or scala? Or could anyone explain how it's done? I can't find any information on this...
The DBpedia Spotlight wiki pages would be a good place to start.
And I believe the installation page has listed the most popular ways (using a jar, or set up a web service) to use the application.
It includes instructions on using the Java/Scala API with your own installation, or calling the Web Service.
There are some additional data needed to be downloaded to run your own server for full service, good time to make a coffee for yourself.
you need download dbpedia spotlight (jar file) after that u can use next two classes ( author pablomendes ) i only make some change .
public class db extends AnnotationClient {
//private final static String API_URL = "http://jodaiber.dyndns.org:2222/";
private static String API_URL = "http://spotlight.dbpedia.org:80/";
private static double CONFIDENCE = 0.0;
private static int SUPPORT = 0;
private static String powered_by ="non";
private static String spotter ="CoOccurrenceBasedSelector";//"LingPipeSpotter"=Annotate all spots
//AtLeastOneNounSelector"=No verbs and adjs.
//"CoOccurrenceBasedSelector" =No 'common words'
//"NESpotter"=Only Per.,Org.,Loc.
private static String disambiguator ="Default";//Default ;Occurrences=Occurrence-centric;Document=Document-centric
private static String showScores ="yes";
#SuppressWarnings("static-access")
public void configiration(double CONFIDENCE,int SUPPORT,
String powered_by,String spotter,String disambiguator,String showScores){
this.CONFIDENCE=CONFIDENCE;
this.SUPPORT=SUPPORT;
this.powered_by=powered_by;
this.spotter=spotter;
this.disambiguator=disambiguator;
this.showScores=showScores;
}
public List<DBpediaResource> extract(Text text) throws AnnotationException {
LOG.info("Querying API.");
String spotlightResponse;
try {
String Query=API_URL + "rest/annotate/?" +
"confidence=" + CONFIDENCE
+ "&support=" + SUPPORT
+ "&spotter=" + spotter
+ "&disambiguator=" + disambiguator
+ "&showScores=" + showScores
+ "&powered_by=" + powered_by
+ "&text=" + URLEncoder.encode(text.text(), "utf-8");
LOG.info(Query);
GetMethod getMethod = new GetMethod(Query);
getMethod.addRequestHeader(new Header("Accept", "application/json"));
spotlightResponse = request(getMethod);
} catch (UnsupportedEncodingException e) {
throw new AnnotationException("Could not encode text.", e);
}
assert spotlightResponse != null;
JSONObject resultJSON = null;
JSONArray entities = null;
try {
resultJSON = new JSONObject(spotlightResponse);
entities = resultJSON.getJSONArray("Resources");
} catch (JSONException e) {
//throw new AnnotationException("Received invalid response from DBpedia Spotlight API.");
}
LinkedList<DBpediaResource> resources = new LinkedList<DBpediaResource>();
if(entities!=null)
for(int i = 0; i < entities.length(); i++) {
try {
JSONObject entity = entities.getJSONObject(i);
resources.add(
new DBpediaResource(entity.getString("#URI"),
Integer.parseInt(entity.getString("#support"))));
} catch (JSONException e) {
LOG.error("JSON exception "+e);
}
}
return resources;
}
}
second class
/**
* #author pablomendes
*/
public abstract class AnnotationClient {
public Logger LOG = Logger.getLogger(this.getClass());
private List<String> RES = new ArrayList<String>();
// Create an instance of HttpClient.
private static HttpClient client = new HttpClient();
public List<String> getResu(){
return RES;
}
public String request(HttpMethod method) throws AnnotationException {
String response = null;
// Provide custom retry handler is necessary
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(3, false));
try {
// Execute the method.
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
LOG.error("Method failed: " + method.getStatusLine());
}
// Read the response body.
byte[] responseBody = method.getResponseBody(); //TODO Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
// Deal with the response.
// Use caution: ensure correct character encoding and is not binary data
response = new String(responseBody);
} catch (HttpException e) {
LOG.error("Fatal protocol violation: " + e.getMessage());
throw new AnnotationException("Protocol error executing HTTP request.",e);
} catch (IOException e) {
LOG.error("Fatal transport error: " + e.getMessage());
LOG.error(method.getQueryString());
throw new AnnotationException("Transport error executing HTTP request.",e);
} finally {
// Release the connection.
method.releaseConnection();
}
return response;
}
protected static String readFileAsString(String filePath) throws java.io.IOException{
return readFileAsString(new File(filePath));
}
protected static String readFileAsString(File file) throws IOException {
byte[] buffer = new byte[(int) file.length()];
#SuppressWarnings("resource")
BufferedInputStream f = new BufferedInputStream(new FileInputStream(file));
f.read(buffer);
return new String(buffer);
}
static abstract class LineParser {
public abstract String parse(String s) throws ParseException;
static class ManualDatasetLineParser extends LineParser {
public String parse(String s) throws ParseException {
return s.trim();
}
}
static class OccTSVLineParser extends LineParser {
public String parse(String s) throws ParseException {
String result = s;
try {
result = s.trim().split("\t")[3];
} catch (ArrayIndexOutOfBoundsException e) {
throw new ParseException(e.getMessage(), 3);
}
return result;
}
}
}
public void saveExtractedEntitiesSet(String Question, LineParser parser, int restartFrom) throws Exception {
String text = Question;
int i=0;
//int correct =0 ; int error = 0;int sum = 0;
for (String snippet: text.split("\n")) {
String s = parser.parse(snippet);
if (s!= null && !s.equals("")) {
i++;
if (i<restartFrom) continue;
List<DBpediaResource> entities = new ArrayList<DBpediaResource>();
try {
entities = extract(new Text(snippet.replaceAll("\\s+"," ")));
System.out.println(entities.get(0).getFullUri());
} catch (AnnotationException e) {
// error++;
LOG.error(e);
e.printStackTrace();
}
for (DBpediaResource e: entities) {
RES.add(e.uri());
}
}
}
}
public abstract List<DBpediaResource> extract(Text text) throws AnnotationException;
public void evaluate(String Question) throws Exception {
evaluateManual(Question,0);
}
public void evaluateManual(String Question, int restartFrom) throws Exception {
saveExtractedEntitiesSet(Question,new LineParser.ManualDatasetLineParser(), restartFrom);
}
}
main()
public static void main(String[] args) throws Exception {
String Question ="Is the Amazon river longer than the Nile River?";
db c = new db ();
c.configiration(0.0, 0, "non", "CoOccurrenceBasedSelector", "Default", "yes");
System.out.println("resource : "+c.getResu());
}
I just add one little fix for your answer.
Your code is running, if you add the evaluate method call:
public static void main(String[] args) throws Exception {
String question = "Is the Amazon river longer than the Nile River?";
db c = new db ();
c.configiration(0.0, 0, "non", "CoOccurrenceBasedSelector", "Default", "yes");
c.evaluate(question);
System.out.println("resource : "+c.getResu());
}
Lamine
In the request method of the second class (AnnotationClient) in Adel's answer, the author Pablo Mendes hasn't finished
TODO Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
which is an annoying warning that needs to be removed by replacing
byte[] responseBody = method.getResponseBody(); //TODO Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
// Deal with the response.
// Use caution: ensure correct character encoding and is not binary data
response = new String(responseBody);
with
Reader in = new InputStreamReader(method.getResponseBodyAsStream(), "UTF-8");
StringWriter writer = new StringWriter();
org.apache.commons.io.IOUtils.copy(in, writer);
response = writer.toString();