Using java nio in java ee - java-ee-6

I want to use java nio in java ee.
But I don't know how to do it right.
I need to after server has deploy java.nio.selector always listens the port and processing socket connection.
I try do it there:
#Singleton
#Lock(LockType.READ)
public class TaskManager {
private static final int LISTENINGPORT;
static {
LISTENINGPORT = ConfigurationSettings.getConfigureSettings().getListeningPort();
}
private ArrayList<ServerCalculationInfo> serverList;
public TaskManager() {
serverList = new ArrayList<ServerCalculationInfo>();
select();
}
#Asynchronous
public void select() {
try {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
Selector selector = Selector.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(LISTENINGPORT));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
try {
selector.select();
} catch (IOException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
break;
}
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey selKey = (SelectionKey) it.next();
it.remove();
try {
processSelectionKey(serverSocketChannel, selKey);
} catch (IOException e) {
serverList.remove(serverCalculationInfo);
}
}
}
} catch (IOException e) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, e);
} catch (Exception e) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, e);
}
}
}
It don't work correctly. The process hangs during deploy and redeploy application possible only after restart Glassfish.
How can I do right it?

It works correctly if invoke #Asynchronous method from the #PostConstructor:
#PostConstruct
public void postTaskManager() {
serverList = new ArrayList<ServerCalculationInfo>();
select();
}
instead of invoke it from constructor.
But class must be without #Startup annotation.

Related

ConnectionFactory throwing errors when shared

I've a very simple application that adds messages to a queue and reads them using a MessagerListener.
Edit: I was testing this on a single instance of Artemis that had been setup as part of a two instance cluster on docker.
I want to create the ConnectionFactory once and reuse it for all producers and consumers in the application.
I have created the ConnectionFactory and stored it in a static variable (singleton) so it can be accessed from anywhere.
The aim is that the client use this shared connection factory to create a new connection when required.
However, I have noticed that doing this causes a "Failed to create session factory" when trying to create a new connection.
javax.jms.JMSException: Failed to create session factory
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:886)
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:299)
at com.test.artemistest.jms.QueueTest2.getMessagesFromQueue(QueueTest2.java:137)
at com.test.artemistest.jms.QueueTest2.access$000(QueueTest2.java:61)
at com.test.artemistest.jms.QueueTest2$1.run(QueueTest2.java:75)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: ActiveMQNotConnectedException[errorType=NOT_CONNECTED message=AMQ219007: Cannot connect to server(s). Tried with all available servers.]
at org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.createSessionFactory(ServerLocatorImpl.java:690)
at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:884)
If I create a connection factory per call this error does not occur.
Doing this seems very inefficient.
I've recreated a similar issue below.
If I create the connection factory in the main method the error occurs.
However if created just before use in a method it works as expected.
If I add two listeners the error occurs even though they are in separate threads. Could it be linked to the fact the connections are not closed in the consumers but are in the producers?
Why is this the case and do you recommend sharing the connection factory?
Thanks
public class QueueTest2 {
private static boolean shutdown = false;
private static ConnectionFactory cf;
public static void main(String[] args) {
// uncomment below for error to occur
// QueueTest2.getConnectionFactory("localhost", 61616);
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(new Runnable() {
#Override
public void run() {
getMessagesFromQueue("localhost", 61616);
while (!shutdown) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("getMessagesFromQueue shutdown");
}
});
addMessagesToQueue("localhost", 61616);
// uncommenting below also causes the issue
// executor.execute(new Runnable() {
// #Override
// public void run() {
// getMessagesFromQueue("localhost", 61616);
// while (!shutdown) {
// try {
// Thread.sleep(1000L);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// System.out.println("getMessagesFromQueue shutdown");
// }
// });
addMessagesToQueue("localhost", 61616);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
shutdown = true;
executor.shutdownNow();
}
private static void addMessagesToQueue(String host, int port) {
ConnectionFactory cf2 = getConnectionFactory(host, port);
Connection connection = null;
Session sessionQueue = null;
try {
connection = cf2.createConnection("artemis", "password");
connection.setClientID("Producer");
sessionQueue = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Queue orderQueue = sessionQueue.createQueue("exampleQueue");
MessageProducer producerQueue = sessionQueue.createProducer(orderQueue);
connection.start();
// send 100 messages
for (int i = 0; i < 100; i++) {
TextMessage message = sessionQueue.createTextMessage("This is an order: " + i);
producerQueue.send(message);
}
} catch (JMSException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (sessionQueue != null) {
sessionQueue.close();
}
} catch (JMSException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
}
try {
if (connection != null) {
connection.close();
}
} catch (JMSException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private static void getMessagesFromQueue(String host, int port) {
ConnectionFactory cf2 = getConnectionFactory(host, port);
Connection connection2 = null;
Session sessionQueue2;
try {
connection2 = cf2.createConnection("artemis", "password");
connection2.setClientID("Consumer2");
sessionQueue2 = connection2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Queue orderQueue = sessionQueue2.createQueue("exampleQueue");
MessageConsumer consumerQueue = sessionQueue2.createConsumer(orderQueue);
consumerQueue.setMessageListener(new MessageHandlerTest2());
connection2.start();
Thread.sleep(5000);
} catch (JMSException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(QueueTest2.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static ConnectionFactory getConnectionFactory(String host, int port) {
if (cf == null) {
Map<String, Object> connectionParams2 = new HashMap<String, Object>();
connectionParams2.put(TransportConstants.PORT_PROP_NAME, port);
connectionParams2.put(TransportConstants.HOST_PROP_NAME, host);
TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class
.getName(), connectionParams2);
cf = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);
}
return cf;
}
}
class MessageHandlerTest2 implements MessageListener {
#Override
public void onMessage(Message message) {
try {
System.out.println("new message: " + ((TextMessage) message).getText());
message.acknowledge();
} catch (JMSException ex) {
Logger.getLogger(MessageHandlerTest2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I've run your code, but I don't see any errors. My guess is that there may be a timing issue related to concurrency. Try adding synchronized to your getConnectionFactory method since it can theoretically be called concurrently by multiple threads in your application, e.g.:
private synchronized static ConnectionFactory getConnectionFactory(String host, int port)
I have found a solution that works on a clustered environment and docker.
It involves using the "pooled-jms" connection pool. Something I had planned to use anyway.
Although it does not explain the issues I was seeing above, it is at least a work around until I can investigate further.
The "WARN: AMQ212064: Unable to receive cluster topology " mentioned above appears to have been a red herring as it went away as quickly as it appeared.

Test exception of a method which contains try catch in junit

I have code snippet below.
What I want is if getNames() method catch an exception
( ex. InterruptedException ),
want to check if Got InterruptedException !!! prints out or not.
There are some examples of testing exception for a method
which throws an exception in its method ( ex. String method1() throws InterruptedException {...} ) in the Internet.
But not this case. Does anyone have some thought or idea?
public class A {
public List<String> getNames()
{
String addess = "address1";
int age = 17;
List<String> names = null;
try {
names = getSomeNames(address, sex);
}
catch (InterruptedException | ExecutionException e) {
throw new MyCustomException(e);
}
catch(Exception e) {
throw new MyCustomException(e);
}
return names;
}
List<String> getSomeNames(String address, int sex) throws InterruptedException, ExecutionException
{
// ...
// throw exceptions... at some point
//
return names;
}
}
public class MyCustomException extends Exception {
public MyCustomException(Throwable e) {
if (e.getCause() instanceof InterruptedException) {
// write log
System.out.println("Got InterruptedException !!!");
}
else if (e.getCause() instanceof ExecutionException) {
// write log
System.out.println("Got ExecutionException!!!");
}
else {
// write log
}
}
}
I tried this but the test failed and got NullPointerException in catch block.
#Test
public void testException() {
A objA = spy(new A());
try {
doThrow(MyCustomException.class).when(objA).getNames();
objA.getNnames();
}
catch (Exception e) {
System.out.println(e.getCause().toString()); // ==> throws java.lang.NullPointerException here.
}
}
There are several ways to test it.
First solution is to replace System.out with different stream and read from it later. ( I don't like this approach )
#Test
void whenSayHi_thenPrintlnCalled() throws IOException {
PrintStream normalOutput = System.out;
String result;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream temporalOutput = new PrintStream(baos)) {
System.setOut(temporalOutput);
ThatGuy thatGuy = new ThatGuy();
thatGuy.sayHi();
result = new String(baos.toByteArray(), StandardCharsets.UTF_8);
} finally {
System.setOut(normalOutput);
}
assertEquals("Hi", result.trim());
}
Second one is to use logger instead of just System.out. I consider this approach better not only from testing, but from code design perspective as well. Using this one you can just replace logger with Mockito.mock and user Mockito.verify to check what was called on your logger.
#Test
void whenSayHi_thenCallLogger() {
Logger logger = Mockito.mock(Logger.class);
ThatGuy thatGuy = new ThatGuy();
ReflectionTestUtils.setField(thatGuy, "logger", logger);
thatGuy.sayHiToLog();
verify(logger).error("Hi");
}
Class under testing looks like this:
class ThatGuy {
private static Logger logger = LoggerFactory.getLogger(ThatGuy.class);
void sayHi() {
System.out.println("Hi");
}
void sayHiToLog() {
logger.error("Hi");
}
}

Javafx Task for Bluetooth data reciever

I am creating javafx application where I have this case that I need to listen for data sent over Bluetooth.
I have one fxml window on which I need to initialize Bluetooth and start listening from data.
Following is my Code for fxml controller:
//all imports
public class NewBarcodeInvoicePaneController implements Initializable{
private BluetoothController bc;
public BluetoothController getBc() {
return bc;
}
#Override
public void initialize(URL location, ResourceBundle resources) {
try {
bc = new BluetoothController();
new Thread(bc).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
And BluetoothController is task where I initialize bluettoth and listen to the data
public class BluetoothController extends Task<Void> {
#Override
protected Void call() throws Exception {
LocalDevice local = null;
StreamConnectionNotifier notifier;
StreamConnection connection = null;
// setup the server to listen for connection
try {
local = LocalDevice.getLocalDevice();
try {
local.setDiscoverable(DiscoveryAgent.GIAC);
} catch (BluetoothStateException e) {
}
UUID uuid = new UUID(80087355); // "04c6093b-0000-1000-8000-00805f9b34fb"
String url = "btspp://localhost:" + uuid.toString() + ";name=RemoteBluetooth";
notifier = (StreamConnectionNotifier) Connector.open(url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
try {
System.err.println("THIS IS HAPENING");
connection = notifier.acceptAndOpen();
System.err.println("HAPENING???????????????????????????");
InputStream inputStream = connection.openInputStream();
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream));
String lineRead = bReader.readLine();
connection.close();
inputStream.close();
notifier.close();
local.setDiscoverable(DiscoveryAgent.NOT_DISCOVERABLE);
JSONParser parser = new JSONParser();
Object obj = parser.parse(lineRead);
JSONArray array = (JSONArray) obj;
array.stream().map((o) -> (String) o).forEach((stringObj) -> {
System.out.println(stringObj);
});
System.out.println("AFTER DATA RECIEVED");
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
}
It Works fine if I send data over bluetooth and blocking call to notifier.acceptAndOpen() is unblocked.
My problem is when we do not pass any data and I just want to close the window I opened..
It still have blocking call open with extra thread by the task.
I tried to cancel BluetoothController task in Main controller where I open this window like following
private void openNewBarcodeInvoicePane(ActionEvent ae) {
//following are custom classes to open windows from fxml and getting controller back for further manipulation
PostoryModalWindow modalWindow = new PostoryModalWindow();
modalWindow.openNewModalPaneWithParent("New Invoice", "fxml/newbarcodeinvoicepane.fxml", ae);
//getting controller object
NewBarcodeInvoicePaneController controller = (NewBarcodeInvoicePaneController) modalWindow.getDswFromController();
controller.getWindowStage().showAndWait();
BluetoothController bc = controller.getBc();
if(bc != null){
System.err.println("CANCELLING");
bc.cancel(true);
}
}
But it doesn't throw InterrupttedExeption (In which I might have Choice to close Bluetooth thread) and after research I found that waiting on Socket doesn't work on interrupt.
Any help on this?
Thanks
Got Solution After Some Research.
I just added new task to call notifier.acceptAndOpen();
And added method to close Bluetooth notifier.
public class BluetoothController extends Task<Void> {
private final ObservableList<Item> items = FXCollections.observableArrayList();
public ObservableList<Item> getItems() {
return items;
}
StreamConnectionNotifier notifier;
#Override
protected Void call() throws Exception {
try {
BluetoothConnectionTask bct = new BluetoothConnectionTask(items);
new Thread(bct).start();
Thread.sleep(2000);
notifier = bct.getNotifier();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
public void cancelandExit() {
try {
if (notifier != null) {
notifier.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Here is new task for blocking call
public class BluetoothConnectionTask extends Task<Void>{
private StreamConnectionNotifier notifier;
private StreamConnection connection;
private ObservableList<Item> items = FXCollections.observableArrayList();
public StreamConnection getConnection() {
return connection;
}
public StreamConnectionNotifier getNotifier() {
return notifier;
}
public BluetoothConnectionTask(ObservableList<Item> is){
items = is;
}
#Override
protected Void call() throws Exception {
try {
LocalDevice local = LocalDevice.getLocalDevice();
try {
local.setDiscoverable(DiscoveryAgent.GIAC);
} catch (BluetoothStateException e) {
}
UUID uuid = new UUID(80087355); // "04c6093b-0000-1000-8000-00805f9b34fb"
String url = "btspp://localhost:" + uuid.toString() + ";name=RemoteBluetooth";
notifier = (StreamConnectionNotifier) Connector.open(url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
connection = notifier.acceptAndOpen();
InputStream inputStream = connection.openInputStream();
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream));
String lineRead = bReader.readLine();
connection.close();
inputStream.close();
notifier.close();
LocalDevice local = LocalDevice.getLocalDevice();
local.setDiscoverable(DiscoveryAgent.NOT_DISCOVERABLE);
JSONParser parser = new JSONParser();
Object obj = parser.parse(lineRead);
JSONArray array = (JSONArray) obj;
ItemDAO idao = new ItemDAO();
array.stream().map((o) -> (String) o).forEach((stringObj) -> {
String barcode = (String) stringObj;
Item i = idao.getItemByBarCode(barcode);
System.err.println("Adding Item "+i.getName());
items.add(i);
});
System.out.println("AFTER DATA RECIEVED");
return null;
}
}
Now for cancelling closing my bluetooth thread I am calling cancelandExit() after window is closed.

future.get after ScheduledThreadPoolExecutor shutdown, will it work?

We use the ScheduledThreadPoolExecutor and after submitting the job we call shutdown immediately.
Because as per doc Shutdown does not kill the submitted task, running task and allows it to complete.
The question is after shutdown can we continue to use the future object that the ScheduledThreadPoolExecutor submit returns.
private static Future submitACall(Callable callableDelegate) {
ScheduledThreadPoolExecutor threadPoolExe = null;
try {
threadPoolExe = new ScheduledThreadPoolExecutor(1);
return threadPoolExe.submit(callableDelegate);
} finally {
threadPoolExe.shutdown();
}
}
//in another method...
if(future.isDone())
future.get();
Yes, you can, in a try-catch:
package testsomething;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
public class TestSomething {
private static Future future = null;
private static ScheduledThreadPoolExecutor threadPoolExe = null;
public static void main(String[] args) {
Callable callableDelegate = new MyCallable();
future = submitACall(callableDelegate);
try {
System.out.println("First get: " + ((Integer)future.get()));
} catch (InterruptedException | ExecutionException ex) {
System.out.println("Exception: " + ex);
}
try {
Thread.sleep(100L);
} catch (InterruptedException ex) {
System.out.println("Exception: " + ex);
}
try {
System.out.println("Thread pool shut down? " + threadPoolExe.isShutdown());
System.out.println("Second get through 'anotherMethod': " + anotherMethod());
} catch (InterruptedException | ExecutionException ex) {
System.out.println("Exception: " + ex);
}
}
private static Future submitACall(Callable callableDelegate) {
try {
threadPoolExe = new ScheduledThreadPoolExecutor(1);
return
threadPoolExe.submit(callableDelegate);
} finally {
threadPoolExe.shutdown();
}
}
private static Integer anotherMethod() throws ExecutionException, InterruptedException {
if(future.isDone())
return ((Integer)future.get());
else
return null;
}
private static class MyCallable implements Callable {
#Override
public Object call() throws Exception {
return new Integer(0);
}
}
}

Show previous instance of RCP application

I had an rcp application which runs for only first run, when a user attempts to re-execute the application, second instance behaves as a client which encodes and sends its arguments over the socket to the first instance which acts as a server and then exits silently. The first instance receives and decodes that message, then behaves as if it had been invoked with those arguments.
so far so good i made internal protocol specification for passing arguments between two instances.
I could not bring the first instance(RCP application) to front. It is in minimized state only,
this is in continuation to my previous question
the change i made to previous post is start method of application class
public Object start(IApplicationContext context) throws Exception {
if (!ApplicationInstanceManager.registerInstance()) {
return IApplication.EXIT_OK;
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
System.out.println("New instance detected...");
//Display.getCurrent().getActiveShell()
.forceActive();// this gives null
// pointer exception
// hence commented
}
});
}
});
Display display = PlatformUI.createDisplay();
try {
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART)
return IApplication.EXIT_RESTART;
else
return IApplication.EXIT_OK;
} finally {
display.dispose();
}
}
below line is stopping me to bring Application to front
Display.getCurrent().getActiveShell().forceActive();
generates null pointer exception at getActiveShell()
how can i maximize the previous instance or bring it to front
I wrote an instance manager to restrict my RCP to a single instance.
Here's the code that goes in Application.java, in the start method:
if (!ApplicationInstanceManager.registerInstance()) {
return IApplication.EXIT_OK;
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (DEBUG)
System.out.println("New instance detected...");
Display.getCurrent().getActiveShell().forceActive();
}
});
}
});
Here's the listener interface:
public interface ApplicationInstanceListener {
public void newInstanceCreated();
}
And here's the Manager class:
public class ApplicationInstanceManager {
private static final boolean DEBUG = true;
private static ApplicationInstanceListener subListener;
/** Randomly chosen, but static, high socket number */
public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 44331;
/** Must end with newline */
public static final String SINGLE_INSTANCE_SHARED_KEY = "$$RabidNewInstance$$\n";
/**
* Registers this instance of the application.
*
* #return true if first instance, false if not.
*/
public static boolean registerInstance() {
// returnValueOnError should be true if lenient (allows app to run on
// network error) or false if strict.
boolean returnValueOnError = true;
// try to open network socket
// if success, listen to socket for new instance message, return true
// if unable to open, connect to existing and send new instance message,
// return false
try {
final ServerSocket socket = new ServerSocket(
SINGLE_INSTANCE_NETWORK_SOCKET, 10, InetAddress
.getLocalHost());
if (DEBUG)
System.out
.println("Listening for application instances on socket "
+ SINGLE_INSTANCE_NETWORK_SOCKET);
Thread instanceListenerThread = new InstanceListenerThread(socket);
instanceListenerThread.start();
// listen
} catch (UnknownHostException e) {
EclipseLogging.logError(RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID, e);
return returnValueOnError;
} catch (IOException e) {
return portTaken(returnValueOnError, e);
}
return true;
}
private static boolean portTaken(boolean returnValueOnError, IOException e) {
if (DEBUG)
System.out.println("Port is already taken. "
+ "Notifying first instance.");
try {
Socket clientSocket = new Socket(InetAddress.getLocalHost(),
SINGLE_INSTANCE_NETWORK_SOCKET);
OutputStream out = clientSocket.getOutputStream();
out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes());
out.close();
clientSocket.close();
System.out.println("Successfully notified first instance.");
return false;
} catch (UnknownHostException e1) {
EclipseLogging.logError(RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID, e);
return returnValueOnError;
} catch (IOException e1) {
EclipseLogging
.logError(
RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID,
"Error connecting to local port for single instance notification",
e);
return returnValueOnError;
}
}
public static void setApplicationInstanceListener(
ApplicationInstanceListener listener) {
subListener = listener;
}
private static void fireNewInstance() {
if (subListener != null) {
subListener.newInstanceCreated();
}
}
public static void main(String[] args) {
if (!ApplicationInstanceManager.registerInstance()) {
// instance already running.
System.out.println("Another instance of this application "
+ "is already running. Exiting.");
System.exit(0);
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
System.out.println("New instance detected...");
// this is where your handler code goes...
}
});
}
public static class InstanceListenerThread extends Thread {
private ServerSocket socket;
public InstanceListenerThread(ServerSocket socket) {
this.socket = socket;
}
#Override
public void run() {
boolean socketClosed = false;
while (!socketClosed) {
if (socket.isClosed()) {
socketClosed = true;
} else {
try {
Socket client = socket.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
String message = in.readLine();
if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(
message.trim())) {
if (DEBUG)
System.out.println("Shared key matched - "
+ "new application instance found");
fireNewInstance();
}
in.close();
client.close();
} catch (IOException e) {
socketClosed = true;
}
}
}
}
}
}
After your IApplication start up, you can also check and lock the OSGi instance location using org.eclipse.osgi.service.datalocation.Location.isSet() and org.eclipse.osgi.service.datalocation.Location.lock()
The location is usually retrieved from your Activator using code like:
public Location getInstanceLocation() {
if (locationTracker == null) {
Filter filter = null;
try {
filter = context.createFilter(Location.INSTANCE_FILTER);
} catch (InvalidSyntaxException e) {
// ignore this. It should never happen as we have tested the
// above format.
}
locationTracker = new ServiceTracker(context, filter, null);
locationTracker.open();
}
return (Location) locationTracker.getService();
}