Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 months ago.
Improve this question
public class CloseableResource implements AutoCloseable {
private static boolean _closed = false;
int _n;
public CloseableResource(int n){
}
public void use() throws Exception{
throw new Exception("Exception");
}
#Override
public void close() throws Exception{
_closed = true;
}
public static boolean isClosed() {
System.out.println(_closed);
return _closed;
}
#Test
public void testAutoClose() {
boolean failed = false;
try (CloseableResource res = new CloseableResource(2)) {
assertTrue(res != null);
res.use();
} catch (Exception e) {
assertTrue(CloseableResource.isClosed());
failed = true;
}
assertTrue(failed == true);
failed = false;
try (CloseableResource res = new CloseableResource(3)) {
assertTrue(res != null);
res.use();
} catch (Exception e) {
fail("this code should not be reached");
failed = true;
} finally {
assertTrue(CloseableResource.isClosed());
}
assertTrue(failed == false);
}
I am trying to make that test work, the close method seems to work but I can't figure out why the test doesn't, it always ends up with fail("this code should not be reached"). I need some guidance please.
private static boolean _closed = false; why is this static? Making it static sets it to true or false on all instances instead of on a specific instance. I am not sure this is the desired behavior. When you create a new CloseableResource new resources will remain closed. In the constructor, you MUST set the static _close back to false. This will make your test pass, but it will make for a lousy implementation.
This is what I did to make it "work" with Java 8. With Java 8, there is no way that I know of to really test the auto-closeable attribute of your resource.
public class CloseableResource implements AutoCloseable {
private boolean _closed = false;
int _n;
public CloseableResource() {
_n = 1;
}
// public CloseableResource(int n) {
// _n = n;
// }
public void use() throws Exception {
if (_closed) {
throw new Exception("Attempting to use a closed resource");
}
}
#Override
public void close() throws Exception {
if(_closed) {
throw new Exception ("Attempting to close a closed resource");
}
_closed = true;
}
public boolean isClosed() {
System.out.println(_closed);
return _closed;
}
#Test
public void testAutoClose() {
CloseableResource res = new CloseableResource();
try {
assertTrue(res != null);
res.use();
res.close();
} catch (Exception e) {
fail("This code should not be reached");
}
try {
assertTrue(res != null);
res.use();
} catch (Exception e) {
assertTrue(e.getMessage().equals("Attempting to use a closed resource"));
}
try {
res.close();
} catch (Exception e) {
assertTrue(e.getMessage().equals("Attempting to close a closed resource"));
}
}
}
However, if using Java 9 or greater, you can declare the resource outside the try (it will be effectively final); thus allowing you to test the auto-closeable attribute of your resource effectively.
#Test
public void testAutoClose() {
CloseableResource res = new CloseableResource();
try(res) {
assertTrue(res != null);
res.use();
} catch (Exception e) {
fail("This code should not be reached");
}
try {
res.use();
} catch (Exception e) {
assertTrue(e.getMessage().equals("Attempting to use a closed resource"));
}
try {
res.close();
} catch (Exception e) {
assertTrue(e.getMessage().equals("Attempting to close a closed resource"));
}
}
This will allow you to use the same object to test all conditions in the same test.
Related
I have these 4 methods which each close a different connection type, meaning each of those has a different input object. Each method calls the close() method on the provided input object. Is there a way to combine those methods into one, taking in a generic object? I have no way to implement an interface on the provided objects or extend them.
import java.sql.Statement;
import javax.jms.Connection;
import javax.mail.Transport;
private void close(Statement stm) {
if(stm == null) {
return;
}
try {
stm.close();
} catch (SQLException ex) {
logger.error("Error while closing statement", ex);
}
}
private void close(java.sql.Connection con) {
if(con == null) {
return;
}
try {
con.close();
} catch (SQLException ex) {
logger.error("Error while closing connection", ex);
}
}
private void close(javax.jms.Connection con) {
if(con == null) {
return;
}
try {
con.close();
} catch(JMSException ex) {
logger.error("Error while closing JMS connection", ex);
}
}
private void close(Transport transport) {
if(transport == null) {
return;
}
try {
transport.close();
} catch (MessagingException ex) {
logger.error("Error while closing mail transport", ex);
}
}
EDIT:
Thank you for your answers regarding Java 1.7. Unfortunately our servers are running Java 1.6, so is there any solution for that?
You can use reflection.
First sample give you support for try() with resources:
#Test
public void testRes() throws Exception {
try(ClosableWrapper<StringWriter> rs = new ClosableWrapper<>(new StringWriter())){
Writer wr = rs.getResource();
}
}
static class ClosableWrapper<T> implements AutoCloseable{
private T resource;
private String closeMethod = "close";
public ClosableWrapper(T resource) {
this.resource = resource;
}
public ClosableWrapper(T resource, String closeMethod) {
this.resource = resource;
this.closeMethod = closeMethod;
}
public T getResource() {
return resource;
}
#Override
public void close() throws Exception {
if(resource!=null){
Method m = resource.getClass().getMethod(closeMethod);
m.invoke(resource);
}
}
}
or just one method:
public void close(Object resource) throws Exception {
if(resource!=null){
Method m = resource.getClass().getMethod("close");
m.invoke(resource);
}
}
Assuming these are your classes, use the AutoCloseable interface and put them in a try-with-resource.
I have made this abstract class to automatically retry network calls if some exception is thrown.
I take care to not retry after InterruptedException &
UnknownHostException.
I retry 5 times. After each failure
I perform an exponential back off, starting from 300ms going upto
1500ms.
public abstract class AutoRetry {
private Object dataToReturn = null;
public Object getDataToReturn() {
return this.dataToReturn;
}
public AutoRetry() {
short retry = -1;
while (retry++ < StaticData.NETWORK_RETRY) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
this.dataToReturn = doWork();
break;
} catch (InterruptedException | UnknownHostException e) {
e.printStackTrace();
this.dataToReturn = null;
return;
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected abstract Object doWork() throws IOException;
}
I use it as follows :
final Object dataAfterWork = new AutoRetry() {
#Override
protected Object doWork() throws IOException {
return; //a network call which returns something
}
}.getDataToReturn();
So is this implementation good/correct ?
EDIT
moved to https://codereview.stackexchange.com/questions/87686
This looks pretty good, but I would split the running task from the retry. Also use generics, don't just throw Object about.
Use a Java 8 lambda and the return of the method:
public static <T> Optional<T> doWithRetry(final Supplier<T> t) {
for (int retry = 0; retry <= StaticData.NETWORK_RETRY; ++retry) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
return Optional.of(t.get());
} catch (InterruptedException | UnknownHostException e) {
LOGGER.log(Level.SEVERE, "Call failed.", e);
return Optional.empty();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Call failed. Retry.", e);
}
}
LOGGER.log(Level.SEVERE, "Call failed. Retries exceeded.");
return Optional.empty();
}
Also, use a real logger, not printStackTrace...
Usage:
final String data = doWithRetry(() -> {
//do stuff
});
If your lambda needs to throw an exception, you'll need to define your own #FunctionalInterface:
#FunctionalInterface
interface StuffDoer<T> {
T doStuff() throws Exception;
}
And use that in the method signature, you'll need to handle generic Exception.
Pre-Java 8 usage:
final String data = doWithRetry(new StuffDoer<T>() {
#Override
public T get() throws Exception {
return null;
}
});
public class Midlet extends MIDlet implements CommandListener{
Player p;
public void startApp() {
Display.getDisplay(this).setCurrent(new SongsList(this));
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
notifyDestroyed();
}
public void commandAction(Command cmnd, Displayable dsplbl) {
if (cmnd.getLabel().equals("Exit"))
{
destroyApp(true);
}
else
{
try {
//InputStream is = getClass().getResourceAsStream("/res/getlucky.mpeg");
//p = Manager.createPlayer(is, "audio/mpeg");
p = Manager.createPlayer("http://puu.sh/6n9jC.mp3");
p.realize();
p.start();
} catch (IOException ex) {
ex.printStackTrace();
} catch (MediaException ex) {
ex.printStackTrace();
}
}
}
}
this is the songslist class :
public class SongsList extends List{
public SongsList(Midlet midlet)
{
super("Songs", List.IMPLICIT);
append("get lucky", null);
addCommand(new Command("Exit", Command.EXIT, 0));
addCommand(new Command("Select", Command.OK, 0));
setCommandListener(midlet);
}
}
tried use via file stored in project (its under src/res):
inputStream = getClass().getResourceAsStream("res/getlucky.mpg");
audioPlayer = Manager.createPlayer(inputStream, "audio/mpg");
as well as from HTTP:
//audioPlayer = Manager.createPlayer("http://puu.sh/6n9jC.mp3");
Nothing works, what am I doing wrong?
EDIT:
I've tried to delete my application and just copy paste it to a new project and it worked for some reason.. now I encounter new problems:
1) I try to play a song - this is the link http://puu.sh/6n9jC.mp3
its not playing so I guess there's a limited file size for what can be played can someone tell me what is this limit ?
2) Im trying to record the audio with RecordPlayer but its always null
public AudioAnalyzer()
{
try {
thread = new Thread(this);
recordFinished = false;
//inputStream = getClass().getResourceAsStream("res/getlucky.mpg");
//audioPlayer = Manager.createPlayer(inputStream, "audio/mpg");
audioPlayer = Manager.createPlayer("http://puu.sh/35YTG.mp3");
//audioPlayer = Manager.createPlayer("http://puu.sh/6n9jC.mp3");
audioPlayer.realize();
System.out.println(System.getProperty("supports.audio.capture"));
recordControl = (RecordControl)audioPlayer.getControl("RecordControl");
recordOutput = new ByteArrayOutputStream();
recordControl.setRecordStream(recordOutput);
recordControl.startRecord();
audioPlayer.start();
//thread.start();
} catch (MediaException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
I even tried to print if the system is supporting audio capture and the result were true but I get NullPointException at this line :
recordOutput = new ByteArrayOutputStream();
although I tried to get the recordcontrol from the player it is still null :
recordControl = (RecordControl)audioPlayer.getControl("RecordControl");
I think I read that it'll always give NullPointerException unless you run it on a real device and not an emulator is that true ? can someone verify it ? and if so what can I do if I don't own a device currently any other way to use recordcontrol feature in emulator (assuming recordcontrol isn't working on emulators).
File size is 8MB (maybe play on your phone), try to this code
public void initMedia(final String aFileUrl) {
if (m_player == null) {
try {
m_player = Manager.createPlayer(aFileUrl);
m_player.addPlayerListener(this);
m_player.realize();
m_player.prefetch();
m_volumeControl = (VolumeControl) m_player.getControl("VolumeControl");
} catch (IOException ex) {
} catch (Exception ex) {
} catch (OutOfMemoryError e) {
}
}
}
In your code, i guess you miss "m_player.prefetch()", try this. And print your Exception message...
This code in general for file, resourcce, http...
public void initMedia(final String aProtocol, final String aMediaSource) {
if (m_player == null) {
try {
if (aMediaSource.indexOf("file://") == 0) {
InputStream iRecordStream = Connector.openInputStream(aMediaSource);
m_player = Manager.createPlayer(iRecordStream, "audio/amr");
} else {
m_player = Manager.createPlayer(aProtocol);
}
m_player.addPlayerListener(this);
m_player.realize();
boolean isPrefetch = true;
try {
m_player.prefetch();
} catch (Exception ex) {
isPrefetch = false;
}
// trick to pass prefetch error
if (!isPrefetch) {
if (m_player != null) {
m_player.close();
m_player = null;
}
if (aMediaSource.indexOf("file://") == 0) {
InputStream iRecordStream = Connector.openInputStream(aMediaSource);
m_player = Manager.createPlayer(iRecordStream, "audio/amr");
} else {
m_player = Manager.createPlayer(aProtocol);
}
m_player.addPlayerListener(this);
m_player.realize();
m_player.prefetch();
}
m_volumeControl = (VolumeControl) m_player.getControl("VolumeControl");
} catch (IOException ex) {
} catch (Exception ex) {
} catch (OutOfMemoryError e) {
}
}
}
In general when it comes to J2ME development, you should always test your app on multiple real devices.
Emulators can't be trusted.
Also, J2ME is very fragmented, and various devices have various bugs and behaves differently with the same code. This will affect any app on many areas. One area being audio playback.
For example, some devices requires that you use the realize() and prefetch() methods, while other devices will crash if you use prefetch(). The only possible solution (if you wish to support as many devices as possible) is to use multiple try/catch blocks.
See this link for a detailed explanation and other tips'n'tricks on audio playback with MIDP2.0
http://indiegamemusic.com/help.php?id=1
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
So I want to do destroyProcesses(processes); when I click my stopButton which is a JButton. How would I get this to work in my code?
Here is my code:
private void Processes() throws IOException, InterruptedException {
// New Thread "processesThread" will start here.
final Object mon = threadBlock;
Thread processesThread = new Thread(new Runnable() {
#Override
public void run() {
synchronized (mon) {
try {
try {
Runtime rt = Runtime.getRuntime();
List<Process> processes = new ArrayList<Process>();
// "runnableTogether" will be the number that the user inputs in the GUI.
switch (runnableTogether) {
case 4:
processes.add(rt.exec("C:/Windows/System32/SoundRecorder.exe"));
case 3:
processes.add(rt.exec("C:/Windows/System32/taskmgr.exe"));
case 2:
processes.add(rt.exec("C:/Windows/System32/notepad.exe"));
case 1:
processes.add(rt.exec("C:/Windows/System32/calc.exe"));
Thread.sleep(5000);
destroyProcesses(processes);
break;
default:
System.exit(0);
break;
}
mon.wait();
} catch (IOException ex) {
}
} catch (InterruptedException ex) {
}
}
}
});
processesThread.start();
// New Thread "processesThread" will end here.
}
private void destroyProcesses(List<Process> processes) {
if (processes == null) {
return;
}
else {
for (Process thisProcess : processes) {
thisProcess.destroy();
}
processes.clear();
}
}
public void actionPerformed(final ActionEvent e) {
if (e.getSource() == stopButton) {
try {
// Destroy processes here.
System.exit(0);
}
catch (Exception ex) {
}
}
}
Any ideas?
You need to put the processes as a instance variable, like the following:
public class MyClass {
private List<Process> processes = new ArrayList<Process>();
public MyClass() {
initProcesses();
}
private void initProcesses() {
// init the processes here
}
public void actionPerformed(final ActionEvent e) {
// now here you can use the processes
}
}
Hope that helps!
Move the local variable List<Process> processes = new ArrayList<Process>(); to the class level and add a modifier before declaring the variable, in this case, it was private.
public class yourProgram {
private List<Process> processes = new ArrayList<Process>(); // This was moved from directly after setting up the Runtime.
private void Processes() throws IOException, InterruptedException {
// New Thread "processesThread" will start here.
final Object mon = threadBlock;
Thread processesThread = new Thread(new Runnable() {
#Override
public void run() {
synchronized (mon) {
try {
try {
Runtime rt = Runtime.getRuntime();
// "runnableTogether" will be the number that the user inputs in the GUI.
switch (runnableTogether) {
case 4:
processes.add(rt.exec("C:/Windows/System32/SoundRecorder.exe"));
case 3:
processes.add(rt.exec("C:/Windows/System32/taskmgr.exe"));
case 2:
processes.add(rt.exec("C:/Windows/System32/notepad.exe"));
case 1:
processes.add(rt.exec("C:/Windows/System32/calc.exe"));
Thread.sleep(5000);
destroyProcesses(processes);
break;
default:
System.exit(0);
break;
}
mon.wait();
} catch (IOException ex) {
}
} catch (InterruptedException ex) {
}
}
}
});
processesThread.start();
// New Thread "processesThread" will end here.
}
private void destroyProcesses(List<Process> processes) {
if (processes == null) {
return;
}
else {
for (Process thisProcess : processes) {
thisProcess.destroy();
}
processes.clear();
}
}
public void actionPerformed(final ActionEvent e) {
if (e.getSource() == stopButton) {
try {
// Destroy processes here.
System.exit(0);
}
catch (Exception ex) {
}
}
}
}
I am trying to use Spring batch and implement an aggregated reader (batch file, where multiple records should be treated as one record while writing). Here is the code snippet for my reader:
public class AggregatePeekableReader implements ItemReader<List<T>>, ItemStream {
private SingleItemPeekableItemReader<T> reader;
private boolean process(T currentRecord , InvoiceLineItemsHolder holder) throws UnexpectedInputException, ParseException, Exception {
next = peekNextInvoiceRecord();
// finish processing if we hit the end of file
if (currentRecord == null ) {
LOG.info("Exhausted ItemReader ( END OF FILE)");
holder.exhausted = true;
return false;
}
if ( currentRecord.hasSameInvoiceNumberAndVendorNumber(next)){
LOG.info("Found new line item to current invocie record");
holder.records.add(currentRecord);
currentRecord = null;
return true;
}else{
holder.records.add(currentRecord);
return false;
}
}
private T getNextInvoiceRecord () {
T record=null;
try {
record=reader.read();
} catch (UnexpectedInputException e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
throw e;
} catch (ParseException e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
throw e;
} catch (Exception e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
}
return record;
}
private T peekNextInvoiceRecord() {
T next=null;
try {
next=reader.peek();
} catch (UnexpectedInputException e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
throw e;
} catch (ParseException e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
throw e;
} catch (Exception e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
}
return next;
}
public void close () {
reader.close();
}
public SingleItemPeekableItemReader<T> getReader() {
return reader;
}
public void setReader(SingleItemPeekableItemReader<T> reader) {
this.reader = reader;
}
private class InvoiceLineItemsHolder {
List<T> records = new ArrayList<T>();
boolean exhausted = false;
}
#Override
public void open(ExecutionContext executionContext) throws ItemStreamException {
//
reader.open(executionContext);
}
#Override
public void update(ExecutionContext executionContext) throws ItemStreamException {
// TODO
}
#Override
public List<T> read() throws Exception, UnexpectedInputException, ParseException,
NonTransientResourceException {
CLASS holder = new SOMECLASS()
synchronized (this) {
while (process(getNextInvoiceRecord(), holder)) {
continue;
}
if (!holder.exhausted) {
return holder.records;
} else {
//When you hit the end of the file,close the reader.
close();
return null;
}
}
}
}
The above is a working example for implementing a peekable reader.This peeks the next line
(doesnt read it) and determines whether a logical end of line is reached (some times
multiple lines can make up a single transaction)
You need to implement ItemStream interface for reader. This will give a hint to Spring Batch, that your reader requires some actions to open/close a stream:
public class InvoiceLineItemAggregatePeekableReader extends AbstractItemStreamItemReader<List<SAPInvoicePaymentRecord>> {
#Override
public void close() {
...
}
}
Streams are closed whatever error occurred during step execution. For more examples check classes from Spring Batch itself (e.g. FlatFileItemReader).
I can't move the input file to to an Error folder because the Reader
is not closed
you could copy the file and either use File.deleteOnExit() on the old file for later deletion or delete the old file in an extra step, e.g. with a simple tasklet and a flow which calls the deleteTaskletStep only if the business step had an exception