See the finally part for both in and out - I don't understand why it's checking for null. If all data is consumed, wouldn't in give -1 and out give null? in would therefore close because -1 is not null. under what condition would one in and out be not null and why'd you want to close out when it's not null?
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyBytes {
public static void main(String[] args) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("xanadu.txt");
out = new FileOutputStream("outagain.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
source:
http://docs.oracle.com/javase/tutorial/essential/io/bytestreams.html
If you try to perform a method on a null value, an exception will be thrown. Checking for null ensures that the OutputStream has been set and exists, and that this situation won't occur.
Without closing the stream before the program terminates, you could also lose buffered data. It is always good practice to explicitly manage your resources.
The main point for this is because you don't want to lock up the files if they are not closed and the reason for checking if they are null is because if one of the files was not found to begin with then it would cause an error if you are trying to close something that does not exist.
Related
I am attempting to close a stream coming from an http request using Retrofit and rxjava, either because it timedOut, or because I need to change details that went into the request. Both appear to work perfectly, as when I cancel subscription I get the doOnCancel debug message and when doOnNext is completed I get the doOnTerminate message. I also do not receive inputLines from multiple threads. However, my thread count rises every single time either of the above actions happen. It appears that responsebody.close is not releasing their resources and therefore the thread is not dying (I also have gotten error messages along the lines of "OKHTTP leaked. did you close youre responseBody?")
Does anyone have any suggestions?
public boolean closeSubscription() {
flowableAlive = false;
subscription.cancel();
return true;
}
public void subscribeToFlowable() {
streamFlowable.observeOn(Schedulers.newThread()).subscribeOn(Schedulers.newThread())
.doOnTerminate(() -> log.debug("TERMINATED")).doOnCancel(() -> log.debug("FLOWABLE CANCELED"))
.subscribe(new Subscriber<ResponseBody>() {
#Override
public void onSubscribe(Subscription s) {
subscription = s;
subscription.request(Long.MAX_VALUE);
}
#Override
public void onNext(ResponseBody responseBody) {
log.debug("onNext called");
String inputLine;
try (InputStream inputStream = responseBody.byteStream()) {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
while (flowableAlive && ((inputLine = br.readLine()) != null)) {
log.debug("stream receive input line for thread " + name);
log.debug(inputLine);
}
} catch (IOException e) {
log.debug("error occurred");
log.debug(e.getMessage());
}
}
#Override
public void onError(Throwable t) {
log.debug("error");
flowableAlive = false;
}
#Override
public void onComplete() {
log.debug("completed");
closeSubscription();
flowableAlive = false;
}
});
}
The result of subscribe() is Disposable object. You should store it as a filed and call Disposable.dispose() on it later as shown here:
https://proandroiddev.com/disposing-on-android-the-right-way-97bd55cbf970
Tour OkHttp call will be interrupted properly because dispose() interrupts thread on which the call runs and OkHttp checks regularly if Thread was interrupted to stop transfer when that happened - it's called cooperative cancelling/interruption.
I have a class like this
import java.util.concurrent.*;
public class TestClass<V> {
private final ConcurrentMap<String, Future<V>> requests;
private final ExecutorService executorService;
public TestClass(final ExecutorService executorService) {
this.executorService = executorService;
this.requests = new ConcurrentHashMap<>();
}
public V submitRequest(String cacheKey, Callable<V> request) throws Exception {
final Future<V> task = getOrCreateTask(cacheKey, request);
final V results;
try {
results = task.get();
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException(String.format("Exception while executing request for key '%s'", cacheKey),
e);
} finally {
//Nullpointer here
requests.remove(cacheKey);
}
return results;
}
private synchronized Future<V> getOrCreateTask(String key, Callable<V> request) {
if (requests.containsKey(key)) {
return requests.get(key);
} else {
final Future<V> newTask = executorService.submit(request);
requests.put(key, newTask);
return newTask;
}
}
}
but sometimes under heavy load server throws nullpointer on requests.remove(cacheKey). I have read final when not escaped by this in the constructor is write guaranteed. i.e. other threads can see what is going on with my requests map.
Not sure how do i fix efficiently? Does not like that idea of adding synchronised on the whole parent level method
I'm not actually sure the NPE is where you're identifying it is unless cacheKey is null, which you could check for. The concurrentmap is set correctly so the requests field should never be null. Nevertheless, this code is not correctly synchronized. You are attempting to perform two operations in getOrCreateTask() that while under the synchronized keyword are not correctly synchronized with the map because the map is interacted with in submitRequest when you remove the values.
What is likely happening is that between the check ConcurrentMap#containsKey and ConcurrentMap#get that another thread has removed the value from the cache (ConcurrentMap#remove).
Thread A: Check Contains "foobar" => true
Thread B: Remove "foobar"
Thread A: Call get("foobar") => null
Thread A: Calls Future#get on a null pointer, which then throws a NPE.
Since you control the concurrentmap you can know you'll never have null values. In that case you should instead just call the #get method and check if the returned value is null. This will prevent another thread from removing the value between a contains/get pair since you'll be only accessing the map through one atomic operation.
I want to close browsers after completion of all test. Problem is I am not able to close the browser since the object created ThreadLocal driver does not recognize the driver after completion of test value returning is null.
Below is my working code
package demo;
import java.lang.reflect.Method;
import org.openqa.selenium.By;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ParallelMethodTest {
private static ThreadLocal<dummy> driver;
private int input;
private int length;
#BeforeMethod
public void beforeMethod() {
System.err.println("Before ID" + Thread.currentThread().getId());
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
if (driver == null) {
driver = new ThreadLocal<dummy>();
}
if (driver.get()== null) {
driver.set(new dummy());
}
}
#DataProvider(name = "sessionDataProvider", parallel = true)
public static Object[][] sessionDataProvider(Method method) {
int len = 12;
Object[][] parameters = new Object[len][2];
for (int i = 0; i < len; i++) {
parameters[i][0] = i;
parameters[i][1]=len;
}
return parameters;
}
#Test(dataProvider = "sessionDataProvider")
public void executSessionOne(int input,int length) {
System.err.println("Test ID---" + Thread.currentThread().getId());
this.input=input;
this.length=length;
// First session of WebDriver
// find user name text box and fill it
System.out.println("Parameter size is:"+length);
driver.get().getDriver().findElement(By.name("q")).sendKeys(input + "");
System.out.println("Input is:"+input);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#AfterMethod
public void afterMethod() {
System.err.println("After ID" + Thread.currentThread().getId());
driver.get().close();
}
}
package demo;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
public class dummy {
public WebDriver getDriver() {
return newDriver;
}
public void setNewDriver(WebDriver newDriver) {
this.newDriver = newDriver;
}
private WebDriver newDriver;
public dummy() {
newDriver = new ChromeDriver();
newDriver.get("https://www.google.co.in/");
}
#AfterClass
public void close(){
if(newDriver!=null){
System.out.println("In After Class");
newDriver.quit();
}
}
}
Thanks in Advance.
private static ThreadLocal<dummy> driver is added at the class level. What is happening is that you have already declared the variable at class level. i.e. memory is already allocated to it. Multiple threads are just setting and resetting the values of the same variable.
What you need to do is create a factory that will return an instance of Driver based on a parameter you pass to it.Logic can be anything but taking a general use case example the factory will create a new object and return only if an existing object doesn't exist. Declare and initialise the driver (from factory) in your #Test Methods
Sample code for the factory would be something like
static RemoteWebDriver firefoxDriver;
static RemoteWebDriver someOtherDriver;
static synchronized RemoteWebDriver getDriver(String browser, String browserVersion, String platform, String platformVersion)
{
if (browser == 'firefox')
{
if (firefoxDriver == null)
{
DesiredCapabilities cloudCaps = new DesiredCapabilities();
cloudCaps.setCapability("browser", browser);
cloudCaps.setCapability("browser_version", browserVersion);
cloudCaps.setCapability("os", platform);
cloudCaps.setCapability("os_version", platformVersion);
cloudCaps.setCapability("browserstack.debug", "true");
cloudCaps.setCapability("browserstack.local", "true");
firefoxDriver = new RemoteWebDriver(new URL(URL),cloudCaps);
}
}
else
{
if (someOtherDriver == null)
{
DesiredCapabilities cloudCaps = new DesiredCapabilities();
cloudCaps.setCapability("browser", browser);
cloudCaps.setCapability("browser_version", browserVersion);
cloudCaps.setCapability("os", platform);
cloudCaps.setCapability("os_version", platformVersion);
cloudCaps.setCapability("browserstack.debug", "true");
cloudCaps.setCapability("browserstack.local", "true");
someOtherDriver = new RemoteWebDriver(new URL(URL),cloudCaps);
}
return someOtherDriver;
}
You have a concurrency issue: multiple threads can create a ThreadLocal instance because dummy == null can evaluate to true on more than one thread when run in parallel. As such, some threads can execute driver.set(new dummy()); but then another thread replaces driver with a new ThreadLocal instance.
In my experience it is simpler and less error prone to always use ThreadLocal as a static final to ensure that multiple objects can access it (static) and that it is only defined once (final).
You can see my answers to the following Stack Overflow questions for related details and code samples:
How to avoid empty extra browser opens when running parallel tests with TestNG
Session not found exception with Selenium Web driver parallel execution of Data Provider test case
This is happening because you are creating the driver instance in beforeMethod function so it's scope ends after the function ends.
So when your afterMethod start it's getting null because webdriver instance already destroy as beforeMethod function is already completed.
Refer below links:-
http://www.java-made-easy.com/variable-scope.html
What is the default scope of a method in Java?
I got some questions regarding the use of threads, specially when you have to wait for a thread to be finished so you can perform other operations.
In my app, I use threads for operations such as http connections or when I read from or write to a RecordStore.
For example in the following class that I use to initialize my thread, I retrieve some customers from a webservice using the method called HttpQueryCustomers.
public class thrLoadCustomers implements Runnable {
private RMSCustomer mRMSCustomer;
private String mUrl;
public thrLoadCustomers(RMSCustomer rmsCust, String url) {
mRMSCustomer = rmsCust;
mUrl = url;
}
public void run() {
String jsonResultados = "";
try {
jsonResultados = HttpQueryCustomers();
} catch (IOException ex) {
//How to show a message from here??
} catch (SecurityException se) {
//How to show a message here??
} catch (NullPointerException npe) {
//How to show a message from here??
}
if (!jsonResultados.equals("")) {
try {
mRMSCustomer.save(jsonResultados);
} catch (RecordStoreException ex) {
//How to show a message from here???
}
}
}
public String HttpQueryCustomers() throws IOException,SecurityException,NullPointerException {
StringBuffer stringBuffer = new StringBuffer();
HttpConnection hc = null;
InputStream is = null;
System.out.println(mUrl);
try {
hc = (HttpConnection) Connector.open(mUrl);
if (hc.getResponseCode() == HttpConnection.HTTP_OK) {
is = hc.openInputStream();
int ch;
while ((ch = is.read()) != -1) {
stringBuffer.append((char) ch);
}
}
} finally {
is.close();
hc.close();
}
String jsonData = stringBuffer.toString();
return jsonData.toString();
}
}
Notice in the above class that I pass a parameter called rmsCust of the type RMSCustomer
RMSCustomer is a class that I use to handle all the operations related to RMS:
public class RMSCustomer {
private String mRecordStoreName;
private Customer[] mCustomerList;
public RMSCustomer(String recordStoreName) {
mRecordStoreName = recordStoreName;
}
public Customer[] getCustomers() {
return mCustomerList;
}
public Customer get(int index) {
return mCustomerList[index];
}
public void save(String data) throws RecordStoreException,JSONException,NullPointerException {
RecordStore rs = null;
int idNuevoRegistro;
String stringJSON;
try {
rs = RecordStore.openRecordStore(mRecordStoreName, true);
JSONArray js = new JSONArray(data);
//Set the size of the array
mCustomerList = new Customer[js.length()];
for (int i = 0; i < js.length(); i++) {
JSONObject jsObj = js.getJSONObject(i);
stringJSON = jsObj.toString();
idNuevoRegistro = addRecord(stringJSON, rs);
//Add a new Customer to the array
mCustomerList[i] = initializeCustomer(stringJSON, idNuevoRegistro);
}
} finally {
if (rs != null) {
rs.closeRecordStore();
}
}
}
public int addRecord(String stringJSON, RecordStore rs) throws JSONException,RecordStoreException {
byte[] raw = stringJSON.getBytes();
int idNuevoRegistro = rs.addRecord(raw, 0, raw.length);
return idNuevoRegistro;
}
public Customer initializeCustomer(String stringJSON, int idRecord) throws JSONException {
Customer c = new Customer();
JSONObject jsonObj = new JSONObject(stringJSON);
// Set Customer properties
//...
return c;
}
}
This class is used to show a list of customer and ,as you can see, it extends the List class and receives an array of Customers as a parameter.
public class ListCustomers extends List {
private final Customer[] mData;
public static ListCustomers create(Customer[] data) {
int i = 0;
for (; i < data.length; i++) {
if (data[i] == null) {
break;
}
}
String[] names = new String[i];
for (int j = 0; j < i; j++) {
names[j] = data[j].name;
}
return new ListCustomers(names, data);
}
protected ListCustomers(String names[], Customer[] data) {
super("List of Customer", IMPLICIT, names, null);
mData = data;
}
public Customer getSelectedObject() {
return mData[this.getSelectedIndex()];
}
}
Finally this is how I call the thread from the MIDlet (using all the 3 previous classes) when I want to show a List of Customers:
private void showCustomerList(String url) {
showWaitForm();
if (scrCustomerList == null) {
rmsCustomers = new RMSCustomer("rmsCustomers");
thrLoadCustomers load = new thrLoadCustomers(rmsCustomers, url);
Thread t = new Thread(load);
t.start();
try {
t.join();
} catch (InterruptedException ex) {
}
scrCustomerList = ListCustomers.create(rmsCustomers.getCustomers());
scrCustomerList.addCommand(cmdSelect);
scrCustomerList.addCommand(cmdBack);
scrCustomerList.setCommandListener(this);
}
mDisplay.setCurrent(scrCustomerList);
}
Now here's the problems I have :
The showWaitForm() doesn't work (it sets a form with a Gauge as the
Current form)
I don't know how to show all the exceptions that might be thrown from
within the thrLoadCustomers class.
I don't know whether using t.join() is the best choice
The last question is about something the book I'm reading says :
Threads, in particular, can be a scarce commodity. The MSA
specification requires that an application must be allowed to create
ten threads. Just because you can doesn’t mean you should. In general,
try to use the fewest resources possible so that your application will
run as smoothly as possible
This is the first time a use threads, and in my app I might have up to 10 threads (classes). However, I will only execute once thread at the time, will I be going against what the previous quotation says??
I hope I'm not asking too many questions. Thank you very much for your help.
P.D Much of the code I posted here wouldn't have been possible with the help of Gregor Ophey
Question #1 is about a different problem not related to threading, and for which very little code is shown. I'd suggest you to post a new dedicated question with proper explanation of the issue.
Questions #2 and #3: You could define a wrapper class like this:
public class WSResult {
private boolean success; //true if the WS call went ok, false otherwise
private String errorMessage; //Error message to display if the WS call failed.
private Object result; //Result, only if the WS call succeeded.
private boolean completed = false;
//TODO getter and setters methods here
}
In your screen, you can create an instance of result and wait for it:
WSResult result = new WSResult();
//Start thread here
new Thread(new LoadCustomersTask(result)).start();
//This is old school thread sync.
synchronized(result){
while(!result.isCompleted()){
result.wait();
}
}
//Here the thread has returned, and we can diaplay the error message if any
if(result.isSuccess()){
} else {
//Display result.getErrorMessage()
}
Then your runnable would be like this:
class LoadCustomersTask implements Runnable {
private final WSResult result;
public LoadCustomersTask(WSResult res){
result = res;
}
public void run(){
//Do the WS call
//If it went well
result.setSuccess(true);
result.setResult(jsonResultados);
//Else
result.setSuccess(false);
result.setErrorMessage("Your error message");
//In any case, mark as completed
result.setcompleted(true);
//And notify awaiting threads
synchronized(result){
result.notifyAll();
}
}
}
You can also do it with thread.join, but wait/notify is better because you not making the screen depend on the particular thread where the runnable runs. You can wait/notify on the result instance, as shown, or on the runnable if it is intended for a single use.
Question #4: Yes threads must not be abused, specially in JavaME where programs usually run in single core CPUs with a frecuency in the order of MHz. Try not to have more than 1-3 threads running at the same time. If you really need to, consider using a single thread for running all background tasks (a blocking queue).
I am trying to create a Waveform Control Panel to change the properties of its components. I attempted to apply the example in the Redhawk documentation for a Component Control Panel, but for some reason I get a java.lang.NullPointerException when running the plugin. The error occurs when I attempt to bind the text field to a component property, the exact line where the error occurred is in the comments of the code (at the very bottom).
public class TestControlPanel extends AbstractScaContentEditor<ScaWaveform> {
private ScaWaveform waveform;
private ScaComponent myComponent;
private Text propertyValueField;
private EMFDataBindingContext context;
/**
* {#inheritDoc}
*/
#Override
public void createPartControl(final Composite main) {
main.setLayout(new GridLayout(2, false));
Group controlGroup = new Group(main, SWT.SHADOW_ETCHED_OUT);
controlGroup.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
controlGroup.setText("Controls");
createControlGroup(controlGroup);
}
private void createControlGroup(Composite parent) {
parent.setLayout(new GridLayout(2, false));
EObject input = getInput();
if (input instanceof ScaWaveform) {
// make local copy of waveform
waveform = (ScaWaveform) input;
try {
waveform.refresh(null, RefreshDepth.FULL);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
label = new Label(parent,SWT.None);
label.setText("Property Value:");
propertyValueField = new Text(parent, SWT.BORDER | SWT.FILL);
myComponent = waveform.getScaComponent("myComponent_1");
if(myComponent != null)
{
IObservableValue observable = SCAObservables.observeSimpleProperty(myComponent, "propertyId");
IObservableValue targetObservable = WidgetProperties.text(SWT.Modify).observeDelayed(5000,propertyValueField);
if(observable != null && targetObservable != null)
{
// ***** THE BELOW LINE CAUSES A java.lang.NullPointerException ERROR *****
context.bindValue(targetObservable, observable);
// ***** THE ABOVE LINE CAUSES A java.lang.NullPointerException ERROR *****
}
}
}
}
My original guess for the reason for this error was that one of the IObservableValue variables (e.g. targetObservable or observable) was null, which is why I check to make sure the values are not null before binding them. However, this didn't fix the problem and I still got the same error.
From what code I can see it seems as though your field varible "context" was never initialized.
Simply call the no argument constructor:
context = new EMFDataBindingContext();
It appears that the context variable is null. I see that you define "context" at the top of the class, but I didn't see where it has been set.