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.
Related
Is there a way to test below code.Here I am connecting to database with JNDI.I am new to mockito and not getting a way to test the same.
#SuppressWarnings("unused")
public Connection getJNDIConnection() {
Connection result = null;
try {
InitialContext initialContext = new InitialContext();
if (initialContext == null) {
LOGGER.info("JNDI problem. Cannot get InitialContext.");
}
DataSource datasource = (DataSource) initialContext.lookup(jndiName);
if (datasource != null) {
result = datasource.getConnection();
} else {
LOGGER.info("Failed to lookup datasource.");
}
} catch (NamingException ex) {
LOGGER.error("Cannot get connection: " + ex);
} catch (SQLException ex) {
LOGGER.error("Cannot get connection: " + ex);
}
return result;
}
Of course, you can to do it, but I think you should read the documentation yourself. The main points here is:
InitialContext initialContext = mock(InitialContext.class);
DataSource dataSource = mock(DataSource.class);
Connection expected = mock(Connection.class);
whenNew(InitialContext.class).withNoArguments().thenReturn(initialContext);
when(initialContext.lookup(jndiName)).thenReturn(dataSource);
when(initialContext.getConnection()).thenReturn(connection);
Connection result = intatnceOfCalss.getJNDIConnection();
assertSame("Should be equals", expected, result);
Also you should use PowerMock to mock constructors and static methods. To have deal with Logger, just add this code:
#BeforeClass
public static void setUpClass() {
mockStatic(LoggerFactory.class);
Logger logger = mock(Logger.class);
when(LoggerFactory.getLogger(ApplySqlFileIfExistsChange.class)).thenReturn(logger);
}
Don't forget about annotations:
#RunWith(PowerMockRunner.class)
#PrepareForTest({LoggerFactory.class})
Try to read this doc http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html
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.
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.
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();
}
This is the error which arises when I tried to debug an application under Visual C# 2010
I write that code to retrieve some rows from a database table, I already attached the two well known databases Pubs and Northwind to the db explorer, but the error remains
class Author
{
SqlConnection _pubConnection;
string _connString;
public Author()
{
_connString = "Data Source=./INSTANCE2;Initial Catalog=pubs;Integrated Security=True";
_pubConnection = new SqlConnection();
_pubConnection.ConnectionString = _connString;
}
public int CountAuthors()
{
try
{
SqlCommand pubCommand = new SqlCommand();
pubCommand.Connection = _pubConnection;
pubCommand.CommandText = "Select Count(au_id) from authors";
_pubConnection.Open();
return (int)pubCommand.ExecuteScalar();
}
catch (SqlException ex)
{
throw ex;
}
finally
{
if (_pubConnection != null)
{
_pubConnection.Close();
}
}
}
}
static void Main(string[] args)
{
try
{
Author author = new Author();
Console.WriteLine(author.CountAuthors());
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
the Connection string isn't ok , i correct it and it works fine