How would one find out the jboss port programatically within application/war that is deployed on that jboss server? Using Java
It is a web service running, we don't have any user interface
I am assuming you want the HTTP port.
JBoss publishes a Tomcat connector MBean for each web listener. The naming convention of the mbeans' ObjectNames is:
Domain: jboss.web
Attributes:
address: The binding address
port: The listening port
type: connector
The trick is, without making any assumptions about the bind address or port (the bind address could be 127.0.0.1, or 0.0.0.0 or a host name), finding the correct MBean. To do this, you can use a JMX Query that specifies:
The known domain name: jboss.web
The known type: connector
A wild card for the address: *****
A wild card for the port: *****
An attribute value expression that specifies you are looking for the HTTP/1.1 protocol port (as opposed to the AJP port): Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"))
Once you have an MBeanServerConnection to the JBoss MBeanServer, this statement will return the correct port:
String port = server.queryNames(
new ObjectName("jboss.web:type=Connector,address=*,port=*"),
Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")))
.iterator().next().getKeyProperty("port");
If you are attempting to determine the port from code running inside the JBoss JVM, acquiring the MBeanServerConnection is trivial since you can make a static call to org.jboss.mx.util.MBeanServerLocator.locateJBoss().
Here is an example of a simple JSP to print the HTTP port number:
<%#page contentType="text/html" import="java.util.*,org.jboss.mx.util.*,javax.management.*" %>
<html><head><title>JBoss Web Server Port</title></head><body>
<%
try {
MBeanServerConnection server = MBeanServerLocator.locateJBoss();
String port = server.queryNames(
new ObjectName("jboss.web:type=Connector,address=*,port=*"),
Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")))
.iterator().next().getKeyProperty("port");
out.println("<p>Port:" + port + "</p>");
} catch (Exception e) {
e.printStackTrace(System.err);
}
%></body></html>
If you need to acquire this remotely, you need to use the JBoss client RMIAdaptor. The reference provided by Nayan Wadekar is a good example of how to do this.
If your JBoss server has a org.jboss.mx.remoting.service.JMXConnectorServerService deployed or you are running JBoss using the platform MBeanServer, you can also use the native JMX remoting. Here's a Groovy example of that:
import javax.management.*;
import javax.management.remote.*;
conn = null;
try {
url = new JMXServiceURL("service:jmx:rmi://njw810/jndi/rmi://njw810:1090/jmxconnector");
conn = JMXConnectorFactory.connect(url);
server = conn.getMBeanServerConnection();
objectName = new ObjectName("jboss.web:type=Connector,address=*,port=*"); // HTTP/1.1
println server.queryNames(objectName, Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"))).iterator().next().getKeyProperty("port");
} finally {
try { conn.close(); println "Connection Closed"; } catch (Exception e) {}
}
Related
I'm trying to set up a simple test FTPS server in Java using Apache FtpServer and connect to it using a domain name instead of the IP address.
I've pointed the A record to the IP address and set up the SSL certificate. Based on the Apache FtpServer documentation, here is what my code looks like so far:
FtpServerFactory ftpServerFactory = new FtpServerFactory();
ListenerFactory listenerFactory = new ListenerFactory();
listenerFactory.setPort(990);
listenerFactory.setServerAddress("example.com");
SslConfigurationFactory sslConfigurationFactory = new SslConfigurationFactory();
sslConfigurationFactory.setKeystoreFile(JKS);
sslConfigurationFactory.setKeystorePassword(JKS_PASS);
listenerFactory.setSslConfiguration(sslConfigurationFactory.createSslConfiguration());
listenerFactory.setImplicitSsl(true);
ftpServerFactory.addListener("default", listenerFactory.createListener());
PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
userManagerFactory.setFile(USERS_PATH.toFile());
BaseUser test = new BaseUser();
sample1.setName("test");
sample1.setPassword("test");
sample1.setHomeDirectory(HOME.getAbsolutePath().toString());
test.setAuthorities(List.of(new WritePermission());
UserManager userManager = userManagerFactory.createUserManager();
try {
userManager.save(test);
}
catch (FtpException e) {
e.printStackTrace();
}
ftpServerFactory.setUserManager(userManager);
FtpServer server = ftpServerFactory.createServer();
try {
server.start();
}
catch (FtpException e) {
e.printStackTrace();
}
However, when I try to connect to the FTPS server, I get an ECONNREFUSED - Connection refused by server from my FTPS client.
Are there any steps that I missed?
If your client reports a 'connection refused' that usually indicates (no guarantee) that no firewall prevented the TCP traffic, the connection request ended up on the intended machine but nothing was accepting the connection on the port you tried to connect to.
Things you can check:
Was the server process running? Was the server process on the correct port? Did the client connect to the correct port?
You might try to connect with another client (e.g. curl) just to see whether the TCP connection can be established.
You might try to connect to another port (e.g. 22 / ssh) to see if the client can establish the connection.
Description
I have made a JUnit test that focus on trying to test a call to a SOAP web service.
I am using an embedded tomcat server for my test in order to run my test with a mock server.
I am also using both http and https connectors.
I need to use automatic ports for both these connectors because the test is running on a Jenkins server and i can't just use port 443 or 8443 as they are already taken.
I understand that using the port 0 as standard port will result in tomcat using automatic port allocation but I can't manage to use it with both connectors.
Expected behavior
I'd like to use automatic port allocation also for my custom ssl connector.
Is it possible to do so in some way ?
Sample code
Here is the code for my tomcat instance :
#Before
public void setup() throws Throwable {
File tomcatWorkingDir = new File(mWorkingDir);
//Empty the target/tomcat-working-dir directory if it exist
//Create the directory otherwise
if(tomcatWorkingDir.exists() && tomcatWorkingDir.isDirectory()){
LOGGER.info("cleaning tomcat-working-dir directory");
FileUtils.cleanDirectory(new File(mWorkingDir));
} else {
LOGGER.info("create tomcat-working-dir directory");
tomcatWorkingDir.mkdir();
}
LOGGER.info("disabling ssl certification validation");
//Disable JVM ssl sockets connection
disableJVMCertificate();
//Add server certificate
createServerCertificate();
//Custom SSL Connector
Connector SSLConnector = getSSLConnector();
mTomcat = new Tomcat();
//Standard http startup port
mTomcat.setPort(0);
//Set up base directory
//Otherwise, tomcat would use the current directory
mTomcat.setBaseDir(mWorkingDir);
LOGGER.info("setting the ssl connector in TOMCAT");
Service service = mTomcat.getService();
service.addConnector(SSLConnector);
//Redirect current port
Connector defaultConnector = mTomcat.getConnector();
defaultConnector.setRedirectPort(SERVER_HTTPS_PORT);
//Configure the way WAR are managed by the engine
mTomcat.getHost().setAutoDeploy(true);
mTomcat.getHost().setDeployOnStartup(true);
//Add mock server into our webApp
String servletName = "/server";
File webApp = new File(mWorkingDir,"../../../ws-mock-server/src/main/webapp");
mTomcat.addWebapp(mTomcat.getHost(), servletName, webApp.getAbsolutePath());
//start tomcat
LOGGER.info("starting TOMCAT");
mTomcat.start();
}
and here for my custom ssl connector.
private static Connector getSSLConnector(){
Connector connector = new Connector();
connector.setPort(SERVER_HTTPS_PORT);
connector.setSecure(true);
//Http protocol Http11AprProtocol
connector.setAttribute("protocol", "org.apache.coyote.http11.Http11AprProtocol");
//Maximum threads allowedd on this instance of tomcat
connector.setAttribute("maxThreads","200");
connector.setAttribute("SSLEnabled", true);
//No client Authentification is required in order to connect
connector.setAttribute("clientAuth", false);
//SSL TLSv1 protocol
connector.setAttribute("sslProtocol","TLS");
//Ciphers configuration describing how server will encrypt his messages
//A common cipher suite need to exist between server and client in an ssl
//communication in order for the handshake to succeed
connector.setAttribute("ciphers","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
LOGGER.info("setting keystore file");
//Here an absolute file path is needed in order to properly set up the keystore attribute
connector.setAttribute("keystoreFile",new File(".").getAbsolutePath().replace("\\", "/")+"/"+mWorkingDir+"/server.jks");
LOGGER.info("setting keystore pass");
connector.setAttribute("keystorePass","changeit");
return connector;
}
I have two solutions for this problem:
Select SSL port manually
The ServerSocket(0) constructor automatically selects a free port. The Tomcat uses this method also.
try (ServerSocket testSocket = new ServerSocket(0)) {
int randomFreePort = testSocket.getLocalPort();
sslConnector.setPort(randomFreePort);
defaultConnector.setRedirectPort( randomFreePort);
} // At this point the testSocket.close() called
tomcat.start();
I know, there is a probability, that an another process allocates the same port between the testSocket.close() and tomcat.start(), but you can detect this situation, with LifecycleState.FAILED.equals(sslConnector.getState()) test.
Use lifecycle listeners
Tomcat connectors are lifecycle aware, so you will be notified on 'before_init' and 'after_init' events. Tomcat initializes the connectors in the order as you added them to the Service.
Add the ssl connector.
Add an http connector. (That will be the 'default' connector. Don't call the mTomcat.getConnector() because it gets the first or creates a new connector. )
When the ssl connector initialization complete, you can get the chosen port with getLocalPort() call.
Before the http connector initialization, call the setRedirectPort
Full example:
Tomcat mTomcat = new Tomcat();
Connector sslConnector = getSSLConnector();
mTomcat.getService().addConnector(sslConnector);
Connector defaultConnector = new Connector();
defaultConnector.setPort(0);
mTomcat.getService().addConnector(defaultConnector);
// Do the rest of the Tomcat setup
AtomicInteger sslPort = new AtomicInteger();
sslConnector.addLifecycleListener(event->{
if( "after_init".equals(event.getType()) )
sslPort.set(sslConnector.getLocalPort());
});
defaultConnector.addLifecycleListener(event->{
if( "before_init".equals(event.getType()) )
defaultConnector.setRedirectPort(sslPort.get());
});
mTomcat.start();
I haven't tried it but from the code it looks like
You can setRedirectPort after server was started
You can use Connector.getLocalPort to get actual port
So I think you could try to add something like
mTomcat.start(); // <-- your existing code
defaultConnector.setRedirectPort(SSLConnector.getLocalPort())
I simply publish a web service with the following code in Java:
String dbAccessAddress = "http://127.0.0.1:8024/SmartService";
try {
if (ep != null && ep.isPublished() == false) {
ep = Endpoint.publish(dbAccessAddress, new DbAccess());
logger.info("DbAccess started: " + dbAccessAddress);
}
} catch (Exception ex) {
logger.error("DbAccess failed(" + dbAccessAddress + ")", ex, false);
}
This service works perfectly on localhost but when I try to reach the service from an other computer within the local network, i can not connect to it. Timeout occurs.
I also tried with the browser by writing the service wsdl URL but it can not reach the service. Only works locally.
What is the problem?
The address 127.0.0.1 is reserved for the localhost, this means only local connections are possible. You will have to use a ip address from your local network or simply bind to all interfaces, if you want to your service to be accessible in the local network.
I'm trying to make a java application which uses redis as a backend. Since Redis is a really fast key-value store which I'd like to use, but redis is made to be used with 1 client so it doesn't have an option for user:pass authentication. I'd like to find a way to implement some kind of authentication, so I tried nginx with the redis2 extension. I did this because I could use client-side certficates and HTTPS. But it's making my application really slow.
I'm thinking about using some kind of tunnel which connects to redis via nginx proxy. For this redis would be listen on localhost and there would be an address which I'd like to use to reach redis, but with https authentication. So basically my current method
JAVA - Jedis - LAN - REDIS ,would be
JAVA - Jedis(with localhost as the tunnel entrance?)-
-SSL LAN - Nginx(tunnel exit) - Redis
Any tip for achieving this? I've been googled the web for the last days but i couldn't come up anything that adds only a little overhead to the native connection.
Redis is designed to work on a secure network, behind a backend application. Client applications are not supposed to connect directly to Redis. It makes Redis a poor choice for a 2-tier application.
Now if you still want to use Redis for this, you have several options. You can encapsulate the Redis server in a HTTP interface. This is what the nginx redis2 module provide. You might also want to have a look at webdis, which is similar (and does not depend on nginx). Webdis offers some access control mechanisms. See the documentation.
Another solution is to establish a tunnel, as you proposed. I would not use nginx for this, but just plain old SSH. Let's suppose Redis server runs on machine B (port 6379) and client runs on machine A.
On machine A, I can run:
ssh user#host_B -L 7008:host_B:6379 -N
It will open a tunnel from A to B from local port 7008 (arbitrary choice), and waits. The user should be declared on host B, and its password known. In another session, still on host A, we can now run:
redis-cli -p 7008 ping
Please note a standard Redis client is used. The tunnel handles authentication, encryption and optionally compression in a transparent way for the client.
Now, your client is a Java application, and you probably do not want to run SSH commands to setup the tunnel. Hopefully, you can use the Jsch package to open the tunnel directly from Java. Here is an example with Jedis:
import redis.clients.jedis.*;
import java.util.*;
import com.jcraft.jsch.*;
public class TestTunnel {
Jedis jedis;
Session session;
JSch jsch = new JSch();
int port;
// None of the following should be hardcoded
static String USER = "user"; // SSH user on the redis server host
static String PASSWD = "XXXXXXXX"; // SSH user password
static String HOST = "192.168.1.62"; // Redis server host
static int PORT = 6379; // Redis server port
public TestTunnel() {
try {
// Open the SSH session
session = jsch.getSession( USER, HOST, 22 );
session.setPassword( PASSWD );
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
config.put("Compression", "yes");
config.put("ConnectionAttempts","3");
session.setConfig(config);
session.connect();
// Setup port forwarding from localhost to the Redis server
// Local port is ephemeral (given by the OS)
// Jedis connects to localhost using the local port
port = session.setPortForwardingL( 0, HOST, PORT );
jedis = new Jedis( "127.0.0.1", port );
} catch ( JSchException e ) {
// Proper error handling omitted
System.out.println(e);
}
}
public void disconnect() {
jedis.disconnect();
try {
session.delPortForwardingL( port );
session.disconnect();
} catch ( JSchException e ) {
// Proper error handling omitted
System.out.println(e);
}
}
public void mytest( int n ) {
for ( int k = 0; k < n; k++) {
jedis.set("k" + k, "value"+k);
}
System.out.println("Read: "+jedis.get("k0") );
}
public static void main(String[] args) {
TestTunnel obj = new TestTunnel();
obj.mytest(10);
obj.disconnect();
}
}
It works fine, but please note there is an overhead due to the tunnel. The overhead is very low when the network is slow (the Internet for instance). On a fast LAN (1 GbE), it is much more noticeable: the latency can be multiplied by up to 3 when the tunnel is used. The maximum throughput the Redis server can sustain is also impacted. On server-side, the sshd daemon takes some CPU (more than Redis itself).
That said, I don't think raw performance matters much for a 2-tier application.
Note: There's an SSL version of redis called SSL-REDIS which can be found on github:
https://github.com/bbroerman30/ssl-redis 2.6ish
https://github.com/tritondigital/ssl-redis 2.4ish
With this and modifying the Jedis Java client, SSL authentication could be achieved.
My application is an Spring framework 3.1.2 based Web-application deployed on Apache tomcat 6.
I need to get my running application port-number and host-name on application(server) Start-up. So that I would override it on a property and it is need for Other bean initialization.
Does the spring provides any options to retrieves these details and to set it on Server Startup?..
Take a look into those two questions previously asked: Get the server port number from tomcat with out a request and I need to know the HTTP and HTTPS port my java webapp is running on webapp startup. There you will see how to get port from a Connector, connector also has getDomain method that would give you host name.
Since you know how to get without spring, you can have a bean that gets those details and provides them for the other bean that needs those instantiation detail. There are few ways to do that:
1) Create Spring factory bean that would get port, hostname and instantiates bean you want
2) Have separate bean that holds those details for you and you use that bean to construct other one
3) You override your application details with port and domain and when instantiating bean that needs them have a init method that would read them for your new bean
Here is code for getting port an dip address
class IPAddressDemo{
public static String getIpAddressAndPort1() throws MalformedObjectNameException, NullPointerException,
UnknownHostException {
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
String host = InetAddress.getLocalHost().getHostAddress();
String port = objectNames.iterator().next().getKeyProperty("port");
String ipadd = "http" + "://" + host + ":" + port;
System.out.println(ipadd);
return ipadd;
}
}
Tomcat will run by default on TCP/IP port number 8080.
Steps
Navigate to C:\apache-tomcat-6.0.18\conf\server.xml (The place where you have installed tomcat)
In server.xml file, find Connector port looking like the following
<connector port="8080" protocol="HTTP/1.1" connectiontimeout="20000" redirectport="8443">
</connector>
port in the Connector tag is your port no.
Finding hostnames:
Steps
1. Navigate to `C:\WINDOWS\system32\drivers\etc`
Or
start->All Programs->Run-> type 'drivers' (Without quotes)->etc
Open the file host with a text editor and you can find
127.0.0.1 localhost
From this you can understand what your hostname is.
Thanks.
The ServletRequest object that has been passed to your doGet, or doPost method has getServerName() and getServerPort() methods that provide this information.
Example:
public void doGet(ServletRequest request, ServletResponse response) {
System.out.println("Host Name = " + request.getServerName());
System.out.println("Port Number = " + request.getServerPort());
}