I've an already works code to read an excel file. At first, the API in the controller clase receive the file as MultipartFile type. Then, because of some reasons, I need to convert the MultipartFile into File type. Here is the code:
private static File convert(MultipartFile file) throws IOException {
try {
File convertedFile = new File(file.getOriginalFilename());
convertedFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convertedFile);
fos.write(file.getBytes());
fos.close();
return convertedFile;
} catch (IOException e) {
e.printStackTrace();
throw new IOException("Error in converting the file with error message: " + e.getMessage());
}
}
Here is the service class which called in the controller, which call the convert method above:
public void create(MultipartFile file) throws Exception {
try {
File newFile = convert(file);
// rest of code
} catch (Exception e) {
// rest of code
}
}
Before I try to call the service in a new thread, code above works fine. But, when I try to call the service in a new thread, like below code, it says java.io.FileNotFoundException (The system cannot find the file specified), and the main problem is in this line fos.write(file.getBytes());. Here is how I create the new Thread in the controller:
#RequestMapping(method = RequestMethod.POST, value = "uploadfile")
public ResponseEntity<?> create(#RequestParam (value = "file", required = false) MultipartFile file) throws Exception {
try {
// ...other process
// ================================== code below not work
Thread create;
create = new Thread() {
public void run() {
try {
service.create(file);
} catch (Exception e) {
e.printStackTrace();
}
}
};
create.start();
// ================================== code below not work
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
service.create(file);
} catch (Exception e) {
e.printStackTrace();
}
}
});
t1.start();
// ================================== code below not work
new Thread(() -> {
try {
service.create(file);
} catch (Exception e) {
e.printStackTrace();
}
}){{start();}};
// ...rest of code
} catch (Exception e) {
// ...rest of code
}
}
above is several way how I try to make the thread but none of them works, result with same execption.
Objective: In short, I want to make the file reading in background and immediately send response to client after the service called.
Spring supports async way by return a Callable object. the pseudo code is like:
#RequestMapping(method = RequestMethod.POST, value = "uploadfile")
public Callable<ResponseEntity<?>> create(#RequestParam (value = "file", required = false) MultipartFile file) throws Exception {
return () -> {
try {
service.create(file);
return ResponseEntity.ok()
} catch (Exception e) {
return ResponseEntity.error( /*some error*/
e.printStackTrace();
}
};
}
Here's a tutorial reference : https://niels.nu/blog/2016/spring-async-rest.html .
another reference: How to make a async rest with Spring?
Related
I've written a springboot application to perform etl from data source to another data lake every 15 mins. I've scheduled the execution using #Scheduled annotation to a function.
I had created jar and was executing directly through java -jar ingest.jar. It works fine for some days (3-4 days). And just pauses without any exception. To resume, I have to go and press any key to make it active again.
#Scheduled(initialDelayString = "${ingest.initialdelay.in.seconds}000", fixedRateString = "${ingest.rate.in.seconds}000")
public void ingestData(){
// Ingestion Logic
}
Because the problem persisted, I created war and deployed to the tomcat server. But the problem still remains.
Can somebody point me what am I missing here? The same application works fine if I deploy to cloudfoundry.
IO Streams - FileInputStream and FileOutputStream
Helper Functions for IO
public static void saveLastSuccessfulDate(String filepath, String propertyName, Date dateTime) {
Properties prop = new Properties();
OutputStream output = null;
try {
String lastDate = getDateInFormat(dateTime);
log.info("Saving: " + lastDate);
output = new FileOutputStream(filepath);
prop.setProperty(propertyName, lastDate);
prop.store(output, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//Helper to Write to properties file
public static String checkLastSuccessfulDateAsString(String filepath, String propName) {
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(filepath);
// load a properties file
prop.load(input);
String lastSuccesfulDate = prop.getProperty(propName);
log.info("Last Successful Date: "+lastSuccesfulDate);
return lastSuccesfulDate;
} catch (FileNotFoundException f) {
log.error("checkLastSuccessfulDateAsString: File Not Found: " + f.getMessage());
} catch (IOException ex) {
log.error(ex.getMessage());
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
Regards
In default, spring #Scheduled use single thread. So, if one task was blocking, the next task won't run.
You can make your task class implements SchedulingConfigurer.It will use multithread to run task and avoid blocking. Code like it:
#Component
public class TaskService implements SchedulingConfigurer {
#Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(taskExecutor());
}
#Bean(destroyMethod = "shutdown")
public ScheduledExecutorService taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
// your code
#Scheduled(initialDelayString = "${ingest.initialdelay.in.seconds}000", fixedRateString = "${ingest.rate.in.seconds}000")
public void ingestData(){
// Ingestion Logic
}
}
May help you.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
Calling a java class file using batch file works fine.
Here is the code which is working.
public class TestA {
public static void main(String[] args) {
new TestA().printA();
}
public void printA(){
System.out.println("This is A...");
try {
File file = new File("D:/FileA.txt");
boolean fvar = file.createNewFile();
if (fvar){
System.out.println("File has been created successfully");
}
else{
System.out.println("File already present at the specified location");
}
} catch (IOException e) {
System.out.println("Exception Occurred:");
e.printStackTrace();
}
}
}
The same above code if I put it on scheduling using task executors and try calling the same file using batch file, it's not working ( I mean here file creation is not happening). Need your help on this.
Code with scheduling:
public class TestD implements Runnable {
private ScheduledExecutorService executor = null;
#Override
public void run() {
try {
File file = new File("D:/FileD.txt");
boolean fvar = file.createNewFile();
if (fvar){
System.out.println("File has been created successfully");
}
else{
System.out.println("File already present at the specified location");
}
} catch (IOException e) {
System.out.println("Exception Occurred:");
e.printStackTrace();
}
}
public void executeScheduler() throws SQLException {
executor.scheduleAtFixedRate(this, 2, 5, TimeUnit.SECONDS);
}
public static void main(String args[]){
TestD testD = new TestD();
try {
testD.executeScheduler();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I wrote the code to create a file just to test if my code is being called from the batch file or not, as I couldn't observe the system out statements which are shown in cmd prompt in a jiffy.
Edit:
The reason for this problem is due to NullPointerException but the exception is not able to capture as I'm calling the file using batch and the cmd window not showing the error or probably it's showing the error but not human capturable and window closes in fraction of a second. So I don't think this question is a duplicate of What is a NullPointerException, and how do I fix it?
The issue is due to the variable not initialized and throwing a NullPointerException which is not able to capture in my case. Added a constructor code to initialize the object and it started to work fine.
Modified Code which is working...
public class TestD implements Runnable {
private ScheduledExecutorService executor = null;
public TestC(){
executor = Executors.newScheduledThreadPool(1);
}
#Override
public void run() {
try {
File file = new File("D:/FileD.txt");
boolean fvar = file.createNewFile();
if (fvar){
System.out.println("File has been created successfully");
}
else{
System.out.println("File already present at the specified location");
}
} catch (IOException e) {
System.out.println("Exception Occurred:");
e.printStackTrace();
}
}
public void executeScheduler() throws SQLException {
executor.scheduleAtFixedRate(this, 2, 5, TimeUnit.SECONDS);
}
public static void main(String args[]){
TestD testD = new TestD();
try {
testD.executeScheduler();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I try to realize how to build an true-async http server with Undertow. How to send a response asynchronously if I have another thread which one is processing a request already?
I wrote code like this:
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(exchange -> {
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).thenAccept(string -> {
exchange.getResponseHeaders()
.put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello World");
exchange.endExchange();
}).exceptionally(throwable -> {
System.out.println(throwable.toString());
return null;
});
}).build();
server.start();
but this server response 200 with no data and in logs
java.lang.IllegalStateException: UT000127: Response has already been sent
When I use io.undertow.server.HttpServerExchange#dispatch(java.lang.Runnable) method like this:
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(exchange -> {
exchange.dispatch(() -> {
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).thenAccept(string -> {
exchange.getResponseHeaders()
.put(Headers.CONTENT_TYPE,"text/plain");
exchange.getResponseSender().send("Hello World");
exchange.endExchange();
}).exceptionally(throwable -> {
System.out.println(throwable.toString());
return null;
});
});
}).build();
server.start();
of course a response "Hello World" as expected but server creates new thread for every request!
(jvisualvm after 10 parallel requests)
If you call dispatch() without passing an executor, like this:
exchange.dispatch(() -> {
//...
});
it will dispatch it to the XNIO worker thread pool. It will not necessarily "create new thread for every request".
If you want to not dispatch it to another thread, you should do this:
exchange.dispatch(SameThreadExecutor.INSTANCE, () -> {
//...
});
the undertow not support this way,
i create a new project to solve it:
https://github.com/hank-whu/undertow-async
package io.undertow.async.pingpong;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import io.undertow.async.handler.AsyncHttpHandler;
import io.undertow.async.io.PooledByteBufferInputStream;
import io.undertow.async.io.PooledByteBufferOutputStream;
import io.undertow.connector.ByteBufferPool;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.StatusCodes;
public class PingPongAsyncHttpHandler extends AsyncHttpHandler {
#Override
protected void handleAsyncRequest(HttpServerExchange exchange, PooledByteBufferInputStream content)
throws Exception {
CompletableFuture//
.completedFuture(content)// init
.thenApplyAsync(this::readBytesAndClose)// read
.thenApplyAsync(bytes -> {// write
ByteBufferPool byteBufferPool = exchange.getConnection().getByteBufferPool();
PooledByteBufferOutputStream output = new PooledByteBufferOutputStream(byteBufferPool);
write(output, bytes);
return output;
})//
.thenAcceptAsync(output -> send(exchange, StatusCodes.OK, output));
}
private byte[] readBytesAndClose(PooledByteBufferInputStream content) {
try {
byte[] bytes = new byte[content.available()];
content.read(bytes);
return bytes;
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {// must close it
content.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void write(PooledByteBufferOutputStream output, byte[] bytes) {
try {
output.write("asycn response: ");
output.write(bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
I'm a moderately-experienced C++ guy slowly learning Java. I'm writing a program which needs to do the following:
Create a simple text file, default directory is fine
As the program runs, periodically write one line of data to the file. Depending on a number of factors, the program may write to the file once or a million times. There is no way of knowing which write will be the last.
I've been researching different ways to do this, and this is the working code I've come up with. There are two files, "PeteProgram.java" and "PeteFileMgr.java" :
/*
"PeteProgram.java"
*/
import java.io.*;
import java.lang.String;
public class PeteProgram {
public static void main(String[] args) throws IOException {
String PeteFilename="MyRecordsFile.txt";
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(PeteFilename), "utf-8"));
PeteFileMgr MyPeteFileMgr = new PeteFileMgr(writer);
MyPeteFileMgr.AddThisString(writer, "Add this line #1\n");
MyPeteFileMgr.AddThisString(writer, "Add this line #2\n");
MyPeteFileMgr.AddThisString(writer, "Add this line #3\n");
}
}
//=====================================================================================================
//=====================================================================================================
/*
"PeteFileMgr.java"
*/
import java.io.*;
public class PeteFileMgr {
public PeteFileMgr(Writer writer) {
try {
writer.write("File created!");
} catch (IOException ex) {
// report
} finally {
try {writer.close();} catch (Exception ex) {}
}
}
void AddThisString(Writer writer, String AddThis) {
try {
writer.append(AddThis);
} catch (IOException ex) {
// report
} finally {
try {writer.close();} catch (Exception ex) {}
}
}
}
The initial creation of the file works just fine. However, the to-be-added lines are not written into the file. Because the program compiles and runs with no errors, I assume the program tries to write the added lines, fails, and throws an exception. (Unfortunately, I am working with a primitive compiler/debugger and can't see if this is the case.)
Does anyone spot my mistake?
Many thanks!
-P
That's because you're not flushing the Writer. You should call flush from time to time. Also, you should close your Writer at the end of your app, not after writing content into it. close method automatically flushes the contents of the writer.
So, this is how your code should look like:
public class PeteProgram {
public static void main(String[] args) {
String peteFilename = "MyRecordsFile.txt";
//here's when the physical file is created
Writer writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(peteFilename), "utf-8"));
PeteFileMgr peteFileMgr = new PeteFileMgr(writer);
peteFileMgr.addThisString(writer, "Add this line #1\n");
peteFileMgr.addThisString(writer, "Add this line #2\n");
peteFileMgr.addThisString(writer, "Add this line #3\n");
} catch (IOException e) {
//handle the exception
//basic handling
e.printStacktrace();
} finally {
//this is a must!
try { writer.close(); } catch(IOException silent) { }
}
}
}
public class PeteFileMgr {
public PeteFileMgr(Writer writer) {
try {
//this method is not creating the physical file
writer.write("File created!");
} catch (IOException ex) {
// report
} finally {
//remove this call to close
//try {writer.close();} catch (Exception ex) {}
}
}
public void addThisString(Writer writer, String addThis) {
try {
writer.append(addThis);
} catch (IOException ex) {
// report
} finally {
//remove this call to close
//try {writer.close();} catch (Exception ex) {}
}
}
}
Or if using Java 7 or superior using the try-with-resources:
public class PeteProgram {
public static void main(String[] args) {
String peteFilename = "MyRecordsFile.txt";
//here's when the physical file is created
try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(peteFilename), "utf-8"))) {
PeteFileMgr peteFileMgr = new PeteFileMgr(writer);
peteFileMgr.addThisString(writer, "Add this line #1\n");
peteFileMgr.addThisString(writer, "Add this line #2\n");
peteFileMgr.addThisString(writer, "Add this line #3\n");
} catch (IOException e) {
//handle the exception
//basic handling
e.printStacktrace();
}
}
}
I have a program that needs to load data at launch. The data comes from a serialized object. I have a method loadData(), which is called upon construction of the Data class. Sometimes, (I.e. after a loss of saveData, or on first program launch on a new system), the file can be empty. (The file will exist though, the method ensures that).
When I try to run the program, I recieve an EOFException. So, in the method, I try to catch it, and just print a line to the console explaining what happened and return to the caller of the method. (so, upon return, the program will think loadData() is complete and has returned. However, it still crashes throwing the exception without printing a line to the console or anything. It is like it is totally ignoring the catch I have in place.
CODE:
protected void loadData()
{
// Gets/creates file object.
saveFileObject = new File("savedata.ser");
if(!saveFileObject.exists())
{
try
{
saveFileObject.createNewFile();
}
catch(IOException e)
{
System.out.println("Uh oh...");
e.printStackTrace();
}
}
// Create file input stream
try
{
fileIn = new FileInputStream(saveFileObject);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
// Create object input stream
try
{
inputStream = new ObjectInputStream(fileIn);
}
catch(IOException e)
{
e.printStackTrace();
}
// Try to deserialize
try
{
parts = (ArrayList<Part>)inputStream.readObject();
}
catch(EOFException e)
{
System.out.println("EOFException thrown! Attempting to recover!");
return;
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
// close input stream
try
{
inputStream.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
Any help please?
Try writing your code like :
protected void loadData() {
// Gets/creates file object.
saveFileObject = new File("savedata.ser");
try {
if (!saveFileObject.exists()) {
saveFileObject.createNewFile();
}
// Create file input stream
fileIn = new FileInputStream(saveFileObject);
// Create object input stream
inputStream = new ObjectInputStream(fileIn);
// Try to deserialize
parts = (ArrayList<Part>) inputStream.readObject();
// close input stream
inputStream.close();
} catch (EOFException e) {
System.out.println("EOFException thrown! Attempting to recover!");
} catch (IOException e) {
System.out.println("Uh oh...");
e.printStackTrace();
}
}
Also note that EOFException is a sub-class of IOException
How about making one try and then making catches respectively like here?