JMS connection to a remote MQ with bindings - java

I want to configure a Java application to work with a JMS IBM MQ queue using the bindings file.
I am using the JMSDEMO application provided by IBM.
It works with a local MQ manager but I cannot make it connect to a remote one.
I've generated the bindings file on the remote machine and copied it to my machine.
I've changed the "localhost" in the bindings file to the remote machine name.
However, the app still thinks it should connect to a local QM.
(actually it ignores the hostname settings).
Here's the IBM demo code:
public static final String cfLookup = "JMSDEMOCF";
public static final String JNDITopic = "JMSDEMOTopic";
public static final String JNDIQueue = "JMSDEMOQueue";
public static final String icf ="com.sun.jndi.fscontext.RefFSContextFactory";
........
static String url = "file:C:\\JMSDEMO\\JNDI";
..........
Hashtable environment = new Hashtable();
environment.put(Context.INITIAL_CONTEXT_FACTORY, icf);
environment.put(Context.PROVIDER_URL, url);
ctx = new InitialDirContext( environment );
connFactory = (ConnectionFactory)ctx.lookup( cfLookup );
connection = connFactory.createConnection();
connection.start();
Here are some fragments of the bindings file (JMSDEMOCF is the name of the connection factory)
JMSDEMOCF/RefAddr/3/Content=<the remote machine name or IP; both ignored>
JMSDEMOCF/RefAddr/29/Content=<the remote machine name or IP; both ignored>(the remote port)
It also has the following line:
JMSDEMOCF/RefAddr/116/Type=XMSC_WMQ_LOCAL_ADDRESS
but deleting it changes nothing.

Create a new connection factory in your "bindings file" with MQ Explorer (why are you trying to edit the file by hand?), and specify the Transport option as MQ Client on this new connection factory (the default is Bindings, which is the local connection mode).
On the Connection tab specify the address of the QM, and on the Channels tab the server connection channel to be used to connect to the QM.
Use the new connection factory in your application when connecting from a remote host. You may need to include some additional MQ JARs in the classpath.

Related

Can't connect to corporate machine with SSH JCraft JSch

I've got a problem with connecting to corporate machine with SSH using JCraft JSch.
public static void main(String[] args) throws JSchException {
JSch jSch = new JSch();
String username = "username";
String host = "host";
int port = 22;
jSch.addIdentity("Path\\to\\key\\file");
jSch.setKnownHosts("known_hosts");
/* In known_hosts file, I've got Host IP, and public key,
the same that's on server
*/
Session session = jSch.getSession(username,host,port);
Properties config = new Properties();
config.put("StrictHostKeyChecking","yes");
session.setConfig(config);
session.connect(5000);
}
That's my code, after running it, there is an error: HostKey has been changed: [host adress], if i change StrictHostKeyChecking to no, another error appears: Auth fail.
I can connect to that machine via PuTTy or WinSCP, and I dont need to use tunneling. Also the key format is right(I made that mistake allready). When I connect to the machine via PuTTy, I need to pick the right machine(there are 5), and each of them has their own key pair, and the main connection to the "menu", has also it's own key pair, it's CAPI key.
Does anyone had something like that before? Also I made a forwarding port, and tried to connect with that, but I'm not sure how it works. Can anyone tell me how to do the port forwarding, or maybe somebody has another idea.
Thanks in advice

How to specify the network interface when using Naming Service lookup using Oracle Java ORB

So I'm currently hosting a service which utilizes Oracle's Interoperable Naming Service (INS) according to tutorial listed below. This service deploys a servant on one machine and registers it with the INS, we'll call this machine A.
Properties properties = System.getProperties( );
properties.put( "com.sun.CORBA.POA.ORBPersistentServerPort",
Integer.toString(1060);
ORB orb = ORB.init( args, properties );
ServiceImpl servant = new ServiceImpl( );
POA rootPOA = POAHelper.narrow( orb.resolve_initial_references( "RootPOA" ));
rootPOA.the_POAManager().activate();
rootPOA.activate_object( servant );
((com.sun.corba.se.impl.orb.ORBImpl) orb).
register_initial_reference("PingService",
rootPOA.servant_to_reference(servant));
System.out.println( "INS Server is Ready...");
orb.run();
https://docs.oracle.com/javase/8/docs/technotes/guides/idl/INStutorial.html
When I use a client on the same machine according to the tutorial, everything works just fine. However, when I attempt to do a lookup over LAN, when the INS Server is hosted on Machine A and the client is on Machine B I get an error when narrowing the reference.
String[] argv = new String[]{"-ORBInitRef",
"PingService=corbaloc:iiop:1.2#"
+ ORBIP + ":" + ORBPort + "/PingService"};
ORB orb = ORB.init( argv, null );
org.omg.CORBA.Object object = orb.resolve_initial_references(
"PingService" );
Service fileRef = ServiceHelper.narrow( object ); // <----- error
I set the server as 192.168.0.XXX and it is accessible by machine B, and get error somewhere along these lines. AFAIK the connection is being made to the naming service and the object located in the service, but when it tries to look up the object it uses an incorrect interface on machine A. Then the error is returned to machine B.
com.sun.corba.se.impl.transport.SocketOrChannelConnectionImpl <init>
WARNING "IOP00410201: (COMM_FAILURE)Connection failure: socketType: IIOP_CLEAR_TEXT; hostname: 127.0.1.1; port:1060"
org.omg.CORBA.COMM_FAILURE: vmcid: SUN minor code: 201 completed: No
connectFailure
So my question is, is there a way to specify exactly which interface the naming service can use when it does the lookup? I tried on both a Windows host and a Linux host. The linux host used an iface which wasn't listed but was in the /etc/hosts file and the Windows host used an IP of the last interface listed in ipconfig (a 172.xx.. IP). Tested both on vbox with bridge enabled. Is there an effective way to specify the network interface? My requirement is for the server and client to exist independently on the same LAN. Setting the ORBInitialHost property on the server didn't do anything.
the problem here is that the client machine is searching for the server locally this why it's writing Connection failure: socketType: IIOP_CLEAR_TEXT; hostname: 127.0.1.1; port:1060
So in the client code instead of initializing the properties like this :
String[] argv = new String[]{"-ORBInitRef", "PingService=corbaloc:iiop:1.2#"
+ ORBIP + ":" + ORBPort + "/PingService"};
ORB orb = ORB.init( argv, null );
try initializing it like this :
Properties props = new Properties();
props.put("org.omg.CORBA.ORBInitialHost",ORBIP);
props.put("org.omg.CORBA.ORBInitialPort","1060");
ORB orb = ORB.init(args,props);
in the ORBIP variable put the server IP address in the LAN .
you tried the ORBInitialHost property on the server but it doesn't do anything because he's running locally . this property must be used in the client side to know the exact hosting point of the server.

UnSatisfied Link Exception While sending a message to ibm-mq

I am new to MQ, I have a requirement where in I have to send a mq message from 1 system to another. The Message queue and Queue Manager is Set up at the server, and i only have the qname and the mqmanager name,I have written the following code to create a connection to mq, but i am getting this Exception:
UnsatisfiedLinkError: mqjbnd (Not found in java.library.path)
The code is:
package com.demo.mqsamplimport com.ibm.mq.MQC;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.MQConstants;
public class MQSample {
private static final String qManager = "(MyQueueManagerName)";
private static final String qName = "(MyQueueName)";
public static void putGet(String args[]) {
try {
MQQueueManager qMgr = new MQQueueManager(qManager);
int openOptions = MQConstants.MQOO_OUTPUT;
MQQueue queue = qMgr.accessQueue(qName, openOptions);
MQMessage msg = new MQMessage();
msg.writeString("Hello World!");
MQPutMessageOptions pmo = new MQPutMessageOptions();
queue.put(msg, pmo);
}
catch (MQException ex) {
ex.printstacktrace();
}
catch (java.io.IOException ex) {
ex.printstacktrace(););
}
}
}
can anyone please help me on this.
UnsatisfiedLinkError: mqjbnd (Not found in java.library.path) error is normally caused when you try to make a binding mode connection to IBM MQ Queue Manager hosted on the same server and the IBM MQ Classes for Java can not locate the library mqjbnd. If you do not specify a hostname and channel name for IBM MQ Classes for Java to use to connect, they default to a binding mode connection.
If your applications runs on the same server as the IBM MQ Queue Manager then you would need to tell the client how to find the mqjbnd libraries (on Linux this is /opt/mqm/java/lib) with one of the following methods:
set the LIBPATH environment variable for example on Linux bash export LIBPATH=/path/to/library
With the command line option -Djava.library.path=/path/to/library
Programmatically with System.setProperty("java.library.path", "/path/to/library");
If you are trying to connect to a IBM MQ Queue Manager hosted on a remote server I agree with #user7790438 that you would need to provide MQ with the details on how to connect to the remote queue manager. The MQEnvironment is global and not thread safe. You should use a hashtable to pass these values for example:
import java.util.Hashtable;
private static String host = "dns.name";
private static int port = 1414;
private static String channel = "MQ.SVRCONN.CHL";
Hashtable properties = new Hashtable<String, Object>();
properties.put("hostname", host);
properties.put("port", port);
properties.put("channel", channel);
MQQueueManager qMgr = new MQQueueManager(qManager, properties);
You do not mention what version of IBM MQ the queue manager is, or what version of IBM MQ classes for Java jar files you are referencing. Other details can be passed via the hash table, for example if you are using IBM MQ v8 or later Classes for Java and connecting to a IBM MQ v8 or later Queue Manager you may need to pass a UserID and Password, this would be accomplished by adding the following to the has table:
private static String user = "UserID";
private static String password = "Password";
properties.put(MQConstants.USE_MQCSP_AUTHENTICATION_PROPERTY, true);
properties.put(MQConstants.USER_ID_PROPERTY, user);
properties.put(MQConstants.PASSWORD_PROPERTY, password);
Please note that per the IBM v9.0 Knowledge center page "Deprecated, stabilized and removed features", IBM MQ Classes for Java have been Stabilization as of v8.0. This means that no further enhancements will be made and eventually IBM will deprecated the IBM MQ Classes for Java. You may want to write your application using the IBM MQ classes for JMS which has no support restrictions.
Stabilization of IBM MQ classes for Java
IBM will make no further enhancements to the IBM MQ classes for Java and they are functionally stabilized at the level shipped in IBM MQ Version 8.0. Existing applications that use the IBM MQ classes for Java will continue to be fully supported, but this API is stabilized, so new features will not be added and requests for enhancements rejected. Fully supported means that defects will be fixed together with any changes necessitated by changes to IBM MQ System Requirements.
You instantiated MQQueueManager before setting MQEnvironment's hostname and channel.
Just try add this:
MQEnvironment.hostname = "mq hostname";
MQEnvironment.channel = "mq channel";
Before:
MQQueueManager qMgr = new MQQueueManager(qManager);

Websphere MQ unable to create initial JNDI context

I am trying to run a demo class (JMSJNDIProducer.java) that comes with Websphere MQ 7.0 installation at 'websphere installation location'\tools\jms\samples. I have Websphere up and running, below are my websphere configurations...
Queue Manager Name: JMSDEMO
Queue Manager Port: 1414
Channel (default): SYSTEM.DEF.CLNTCONN
Queue Name: JMSDEMO.QL
let me know if more info needed...
My code is failing during the initial context creation, I'm very new to Websphere MQ and not sure what the initialContextUrl needs to be?
public class JMS_JNDI_Websphere_Sample {
private static String initialContextUrl = "tcp://localhost:1414";
public static void main(String args[]) {
// Instantiate the initial context
String contextFactory = "com.sun.jndi.fscontext.RefFSContextFactory";
Hashtable<String, Object> environment = new Hashtable<String, Object>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
environment.put(Context.PROVIDER_URL, initialContextUrl);
try {
Context context = new InitialDirContext(environment);
} catch (NamingException e) {
e.printStackTrace();
}
System.out.println("Initial context found!");
}
}
I am getting the below exception.
javax.naming.InvalidNameException: tcp://localhost:1414 [Root exception is java.net.MalformedURLException: unknown protocol: tcp]
at com.sun.jndi.fscontext.FSContextFactory.getFileNameFromURLString(FSContextFactory.java:119)
at com.sun.jndi.fscontext.RefFSContextFactory.createContext(RefFSContextFactory.java:41)
at com.sun.jndi.fscontext.RefFSContextFactory.createContextAux(RefFSContextFactory.java:47)
at com.sun.jndi.fscontext.FSContextFactory.getInitialContext(FSContextFactory.java:49)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.InitialContext.<init>(InitialContext.java:197)
at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:82)
at com.hcsc.jms.websphere.jndi.JMS_JNDI_Websphere_Sample.main(JMS_JNDI_Websphere_Sample.java:32)
Caused by: java.net.MalformedURLException: unknown protocol: tcp
at java.net.URL.<init>(URL.java:574)
at java.net.URL.<init>(URL.java:464)
at java.net.URL.<init>(URL.java:413)
at com.sun.jndi.fscontext.FSContextFactory.getFileNameFromURLString(FSContextFactory.java:117)
... 9 more
private static String initialContextUrl = "tcp://localhost:1414";
First off, I don't think "tcp" is a valid value and if it is, do you have something running on port 1414 to reply JNDI lookup requests?
Secondly, I think you are confusing MQ port 1414 with JNDI lookup.
Third, why don't you just follow the example in JmsJndiProducer.java and use a file-based JNDI.
i.e. Use MQ Explorer and select "JMS Administered Objects" then do file-based JNDI.
Once you create your file-based JNDI then that value for your initial context.
You need to separate out the concept of messaing as provided by the JMS API, and the lookup of an object via JNDI. As Roger said the issue is confusion between the MQ listener and the JNDI URL
JNDI is split into the interface used to bind and lookup objects in the directory and the 'service providers' that take the object and put into some persistent store. The com.sun.jndi.fscontext.RefFSContextFactory is a service provider that uses the file system, so the URL for this needs to be an EXISTING directory. When objects are 'bound' into that the .bindings file is created (or updated if objects are already there). You don't need to create the .bindings file; that file is created for you by the File System Context. Also don't modify this by hand.
Typically you would use a LDAP backed JNDI service provider for production usage. The 'lookup' APIs used in the application are the same; what would change are the provider URL (as the location of the LDAP server would be provided) and possible the object name.
Would suggest reviewing Oracle's JNDI tutorial ..

Connect remotely to an H2 Database using a Java Application

I'm having the following problem:
When I try to createTcpServer with my external IP address (the PC's IP and not my local IP = the one we see as an output after running ipconfig in cmd.exe) the following error occurs:
Error with Server: Exception opening port "9092" (port may be in use), cause: "java.net.BindException: Cannot assign requested address: JVM_Bind" [90061-169]
However, the port is not in use. I've checked that using netstat -a -n .
I have enabled my external IP and I have disabled the firewall from the router. My external IP can now be pinged.
Please help me.
Update: Here is my code to start the tcp server.
package businessApp;
import org.h2.tools.Server; //imports the server utility
public class startTcpServerForH2 {
Server server; //the server's instance variable
private static final String SERVER_IP = "192.168.1.101"; //fixed IP of the server
private static final String SERVER_PORT = "9092"; //fixed port the server is listening to
public void tcpServer() { //method responsible to create the tcp server
optionPane optPane = new optionPane(); //option pane for debugging purposes, shows the server's status
try { //catches any server related errors, if the connection is broken etc.
//server uses the IP and port defined earlier, allows other computers in the LAN to connect and implements the secure socket layer (SSL) feature
server = Server.createTcpServer( //create tcp server
new String[] { "-tcpPort" , SERVER_PORT , "-tcpAllowOthers" , "-tcpSSL" }).start();
System.out.println(server.getStatus()); //prints out the server's status
optPane.checkServerStatus(server.getStatus()); //prints out the server's status on the option pane as well
} catch(Exception ex){
System.out.println("Error with Server: " + ex.getMessage());
}
}
public static void main(String[] args){
startTcpServerForH2 tcpServ = new startTcpServerForH2(); //create a new server object
tcpServ.tcpServer(); //starts the tcp server
}
}
Second Update: here is the h2Connection code.
package businessApp;
import java.sql.*; //imports sql features
//Class responsible for connection with H2 Database Engine
public class h2Connection {
Connection conn; //connection variable
DatabaseMetaData dbmd; /** Metadata variable which include methods such as the following:
* 1) Database Product Name
* 2) Database Product Version
* 3) URL where the database files are located (in TCP mode)
*/
Statement stm; //statements variable
ResultSet rst; //result sets variable
private static final String SERVER_IP = "..."; //here I enter my WAN_IP
private static final String SERVER_PORT = "9092";
public Connection connectionToH2(Connection connt) {
optionPane optPane = new optionPane(); //create new option pane object
String outputConn = null; //declare & initialize string which will hold important messages
try {
Class.forName("org.h2.Driver"); //Driver's name
/** The String URL is pertained of the following:
* 1) jdbc which java implements so that it can take advantage of the SQL features
* 2) Which Database Engine will be used
* 3) URL where the files will be stored (as this is a TCP connection)
* 4) Schema: businessApp
* 5) Auto server is true means that other computers can connect with the same databse at any time
* 6) Port number of the server is also defined
*/
String url = "jdbc:h2:tcp://" + SERVER_IP + ":" + SERVER_PORT + "/C:/Databases/businessApp;IFEXISTS=TRUE";
System.out.println(url); //prints out the url the database files are located as well as the h2 features used (SSL)
connt = DriverManager.getConnection(url, "sa", ""); //Driver Manager defines the username & password of the database
System.out.println(connt.getCatalog()); //prints out the database schema
optPane.checkServerStatus(connt.getCatalog()); //prints out the database schema on the option pane as well
connt.setAutoCommit(false); //set AutoCommit to false to control commit actions manually
//outputs H2 version and the URL of the database files which H2 is reading from, for confirmation
dbmd = connt.getMetaData(); //get MetaData to confirm connection
outputConn = "Connection to "+dbmd.getDatabaseProductName()+" "+
dbmd.getDatabaseProductVersion()+ " with the URL " + dbmd.getURL()+" was successful.\n";
System.out.println(outputConn); //outputs the message on the system (NetBeans compiler)
optPane.checkH2Connection(outputConn); //outputs the message on top of the frame
} catch (ClassNotFoundException ex){ //In case there is an error for creating the class for the Driver to be used
System.out.println("Error creating class: " + ex.getMessage());
} catch(SQLException ex){ //Any error associated with the Database Engine
System.out.println("SQL error: " + ex.getMessage());
optPane.checkServerStatus("SQL error: " + ex.getMessage());
}
return connt; //As the method is not void, a connection variable must be returned
}
}
When I want to connect to the h2 database, I make a new h2Connection object and use it to connect. I have followed the H2 manual word by word. What more do you need?
As suggested in the command line help shown below, Protection against Remote Access advises the following:
By default this database does not allow connections from other machines when starting the H2 Console, the TCP server, or the PG server. Remote access can be enabled using the command line options -webAllowOthers, -tcpAllowOthers, -pgAllowOthers.
See the documentation for important caveats regarding these options.
Addendum: Works for me, as long as I restart the Server after opening the firewall; you don't need the setProperty() line at all; the LAN IP to which your WAN_IP forwards port 9092 should be your host IP address; then you can open a shell via your WAN_IP:
java -cp h2.jar org.h2.tools.Shell -url
jdbc:h2:tcp://WAN_IP/~/path/to/test;ifexists=true"
Command line help:
$ java -cp .:/opt/h2/bin/h2.jar org.h2.tools.Shell -?
Interactive command line tool to access a database using JDBC.
Usage: java org.h2.tools.Shell
Options are case sensitive. Supported options are:
[-help] or [-?] Print the list of options
[-url ""] The database URL (jdbc:h2:...)
[-user ] The user name
[-password ] The password
[-driver ] The JDBC driver class to use (not required in most cases)
[-sql ""] Execute the SQL statements and exit
[-properties ""] Load the server properties from this directory
If special characters don't work as expected, you may need to use
-Dfile.encoding=UTF-8 (Mac OS X) or CP850 (Windows).
See also http://h2database.com/javadoc/org/h2/tools/Shell.html
$ java -cp /opt/h2/bin/h2.jar org.h2.tools.Server -?
Starts the H2 Console (web-) server, TCP, and PG server.
Usage: java org.h2.tools.Server
When running without options, -tcp, -web, -browser and -pg are started.
Options are case sensitive. Supported options are:
[-help] or [-?] Print the list of options
[-web] Start the web server with the H2 Console
[-webAllowOthers] Allow other computers to connect - see below
[-webDaemon] Use a daemon thread
[-webPort ] The port (default: 8082)
[-webSSL] Use encrypted (HTTPS) connections
[-browser] Start a browser connecting to the web server
[-tcp] Start the TCP server
[-tcpAllowOthers] Allow other computers to connect - see below
[-tcpDaemon] Use a daemon thread
[-tcpPort ] The port (default: 9092)
[-tcpSSL] Use encrypted (SSL) connections
[-tcpPassword ] The password for shutting down a TCP server
[-tcpShutdown ""] Stop the TCP server; example: tcp://localhost
[-tcpShutdownForce] Do not wait until all connections are closed
[-pg] Start the PG server
[-pgAllowOthers] Allow other computers to connect - see below
[-pgDaemon] Use a daemon thread
[-pgPort ] The port (default: 5435)
[-properties ""] Server properties (default: ~, disable: null)
[-baseDir ] The base directory for H2 databases (all servers)
[-ifExists] Only existing databases may be opened (all servers)
[-trace] Print additional trace information (all servers)
The options -xAllowOthers are potentially risky.
For details, see Advanced Topics / Protection against Remote Access.
See also http://h2database.com/javadoc/org/h2/tools/Server.html

Categories

Resources