I've created a Java application that is split in different subcomponents, each of those runs on a separate Tomcat instance. Also, some components use a MySQL db through Hibernate.
I'm now creating an administration console where it's reported the status of all my Tomcat instances and of MySQL. I don't need detailed information, but knowing if they are running or not it's enough.
What could be the best solution to do that?
Thanks
Most straightforward way would be to just connect the server and see if it succeeds.
MySQL:
Connection connection = null;
try {
connection = DriverManager.getConnection(url, username, password);
// Succes!
} catch (SQLException e) {
// Fail!
} finally {
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
Tomcat:
try {
new URL(url).openConnection().connect();
// Succes!
} catch (IOException e) {
// Fail!
}
If you want a bit more specific status, e.g. checking if a certain DB table is available or a specific webapp resource is available, then you have to fire a more specific SELECT statement or HTTP request respectively.
I assume that you know the ports of which are running in advance (or from configuration files). The easiest way to check is to make socket connections to those ports like a telnet program does. Something like:
public boolean isServerUp(int port) {
boolean isUp = false;
try {
Socket socket = new Socket("127.0.0.1", port);
// Server is up
isUp = true;
socket.close();
}
catch (IOException e)
{
// Server is down
}
return isUp;
}
Usage:
isTomcatUp = isServerUp(8080);
isMysqlUp = isServerUp(3306);
However, I would say that is a false-negative check.. Sometimes it says server UP but the server is stuck or not responding...
I would make sure that what ever monitoring you setup is actually exercising some code. Monitoring the JVM via jmx can also be helpful after the fact. Check out http://www.cacti.net/ .
Firing a simple fixed query through MySQL
SELECT 'a-ok';
and have the .jsp return that a-ok text. If it times out and/or doesn't respond with a-ok, then something's hinky. If you need something more detailed, you can add extra checks, like requesting now() or something bigger, like SHOW INNODB STATUS.
The easiest thing is to look for the MySQL and Tomcat PID files. You need to look at your start scripts to make sure of the exact location, but once you find it, you simply test for existence of the pid file.
Create a servlet as a status page. In the servlet perform a cheap query, if the query succeeds let the servlet print OK otherwise Error. Put the servlet into a war and deploy it to all instances.
This could be used for checks in yor admin console by doing a loop over all instances.
I'd create a simple REST webservice that runs on each Tomcat instance and does a no-op query against the database. That makes it easy to drive from anywhere (command line, web app, GUI app, etc.)
If these are publicly available servers you can use a service like binarycanary.com to poll a page or service in your app.
Related
My program is fetching some images on a min.io server via their Java SDK.
The issue is that even after inputStream.close() the connections remain open from the java code. I can see it with lsof -p <PID>.
After a while, it disappears but sometimes it does not, I guess fast enough, and the java server throws some too many open files errors.
Is there like a garbage collector that removes the connections from the operating system?
How can I prevent these too many open files errors?
Just in case, here is the code:
public static byte[] getImageByImageBinaryId(String imagId) throws IOException {
InputStream object = null;
try {
object = getMinioClientClient().getObject(ServerProperties.MINIO_BUCKET_NAME, imagId);
return IOUtils.toByteArray(object);
} catch (Exception e) {
log.error(e);
} finally {
IOUtils.closeQuietly(object);
}
return null;
}
Internally minio-java uses OkHttp to make HTTP calls. OkHttp, like many Http clients, internally uses a connection pool to speed up repeated calls to the same location. If you need for connections to not persist you can pass in your own OkHttp client to one of the available constructors with your own pooling config but I do not recommend it.
Minio should probably expose a close method to clean up these resources but their expected use case probably involves clients living the whole life of your application.
We are building a websocket webapp for a school project and would like to store the incoming information to MySQL. Currently we are using netbeans and the Server Endpoint is written in Java. The info sent from the client side is a JSON obj. We can decode it but dont't know how to insert it into the table
Problems we are facing
1.We are used to programming Java application and using mysql JDBC but this time we cannot find the library to add, like we use to do.
2.We have tried AJAX but since the PHP is on a different server we cant do it, and I can't find the option to add a PHP file to the current project in netbeans. -- Currently I'm trying to learn how to do AJAX with JSP
3.We think we need to spin a thread so that the reply doesn't have to wait for the insert to complete but when we try to spin a thread the Endpoint no longer works, so we commented it out
4.We are trying to keep third party Frame works to a minimum
Below is the code to our Server Endpoint
public void onMessage(String message, Session session) {
// Create JsonObject from message
JsonObject jsonObject = new Message(message).getJObject();
// Decode JsonObject
message = Decoder(jsonObject);
for (Session peer : peers) {
try {
if (!peer.equals(session)) {
peer.getBasicRemote().sendText(message);
}
} catch (IOException ex) {
Logger.getLogger(ServerEndpoint.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
This is our current decoder. We wanted to spin a thread from this function, I don't know if that is a good idea or not
public String Decoder(JsonObject jObject) {
String message;
message = jObject.getString("msg");
return message;
}
Since Netbeans use Glassfish, I downloaded the MySQL JDBC and put it in the lib folder as I would if I was running Tomcat. Then I go into the Admin console and added the JDBC Connector then added the JDBC Resource. Next restart the server then redeploy the app.
This question already has answers here:
Connect Java to a MySQL database
(14 answers)
Closed 4 years ago.
So I was just wondering, what (and probably, how much...) have I done wrong here with this code?
try {
Class.forName("com.mysql.jdbc.Driver");
Connection c = DriverManager.getConnection("jdbc:mysql://mysql1.000webhost.com/mydatabase", "myusername", "mypassword");
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
As I've triple-checked the username/password, I'm guessing it's something wrong with the host name. The database is only on the server (I don't have any kind of saved local version or anything...do I need to?).
And also, can someone just tell me if I'm on the right lines for what I want to do? Basically I've created a piece of software with a free version and a very cheap paid version. I was thinking that to prevent piracy, since the program requires internet connection anyway, I could store their email address as the username, then their computer's MAC address would be the password (each time the program was run, I would compare the MAC address on their PC with the one registered along with their email in the database. I've got no idea whether that is a good anti-piracy measure, but I was just wondering, if I manage to get the connection working, is that something that I'd be able to do or would there be e.g. security issues with that?
Anyway, thanks in advance :)
if it is not localhost i cannot comment on the host but you also have to give port number.It is missing.
Connection con = DriverManager
.getConnection("jdbc:mysql://"+pHost+":"+pPort+"/Your_mysql_schema_name",username, password);
and also in MYSQL your schema name would be your database name.Ensure that you are giving schema name and also port number.Usually for MYSQL its 3306
Writing a piece of java code to operate your database from a remote connection is not a good idea. Someone could reverse engineer your code and change your data.
You should atleast Implement an simple service on the net that could handle the spam you might receive, and protect your data.
I Think you missed the database port no in your URL .Try this :
try {
Class.forName("com.mysql.jdbc.Driver"); // Not Required for JDBC 4.0 onwards
Connection c = DriverManager.getConnection("jdbc:mysql://mysql1.000webhost.com: 3306/mydatabase", "myusername", "mypassword");
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Try instead of mysql1.000webhost.com to change with server IP address.
Example,
try {
Class.forName("com.mysql.jdbc.Driver");
Connection c = DriverManager.getConnection("jdbc:mysql://123.456.789.012:3306/mydatabase", "myusername", "mypassword");
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
I would recommend you some reading first. This slide show might present you how Java EE applications are build.
Next you might want to read a bit more how to connect your application with a database.
Hibernate is one of the most widely used tools for establishing connection between database and your Java program. It allows you to separate your connection data (e.g. username, password, connection url) from your code with use of configuration files in xml format. The line:
Connection c = DriverManager.getConnection("jdbc:mysql://mysql1.000webhost.com/mydatabase", "myusername", "mypassword");
Is a very dangerous way of establishing connetion, as you are providing confidential credentials inside the code. There are ways to retreive this information from binary files.
You also asked, if is it worth having some local version of your database. The anwser is: Yes. Having your database locally might significantly speed up the time required for development and testing. It also allows you to work on your code even when no internet connection is available.
Providing authentication with use of MAC address is a very dangerous idea. Those addresses are attached to given machines. In other words the user will be able to connect to your application only with machine, on which he or she created an account. When using other computer (e.g. laptop at work) authentication will be denied.
my java server is currently being DDoSed by thousands of different ip's. To counter it, i've been blocking the ip's through the dedicated servers firewall. However just more and more keep coming. This attack is flooding my login server causing players to not be able to login.
I've asked on other places such as a forum for my type of java application, and i've gotten barely any answers. However they told me it's a form of DDoS, also another user referred me to this however I don't believe this would work. http://www.java2s.com/Open-Source/Java-Document/Net/mina-2.0.0-M1/org/apache/mina/filter/firewall/ConnectionThrottleFilter.java.htm
So apparently it's a DoS on my login server, anyone have any clues? I'll provide the login server's main framework below.
try {
shutdownClientHandler = false;
clientListener = new java.net.ServerSocket(serverlistenerPort, 1, null);
misc.println("Login server is now online!");
while (true) {
try {
java.net.Socket s = clientListener.accept();
s.setTcpNoDelay(true);
String connectingHost = s.getInetAddress().getHostName();
if (true) {
if (checkLog("flooders", connectingHost)) {
//misc.println("Flooder Detected, closing connection.");
s.close(); // Closes the connection immediately.
} else {
connections.add(connectingHost);
if (checkHost(connectingHost)) {
misc.println("Connection from "+connectingHost+":"+s.getPort());
try {
playerHandler.newPlayerClient(s, connectingHost);
} catch (Exception E) {misc.println("Login Server crash detected. Protecting...");
s.close();
}
} else {
misc.println("ClientHandler: Rejected "+connectingHost+":"+s.getPort());
s.close();
}
}
} else {
misc.println("ClientHandler: Rejected "+connectingHost+":"+s.getPort());
s.close();
}
Thread.sleep(30;
} catch (Exception e) {
logError(e.getMessage());
}
}
} catch (java.io.IOException ioe) {
if (!shutdownClientHandler) {
misc.println("World is already online!");
} else {
misc.println("ClientHandler was shut down.");
}
}
There are a few options to try to deal with a DDoS, but you need to make certain certain parts are optimized.
For example, your checkLog function needs to be amazingly fast, so you may want to use a 'hashmap' perhaps, so you can quickly check, but, to ensure everything goes fast you may want to look at the ConcurrentHashMap (http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html), so you can better read and write to it.
You could also look at load-balancing your front-end, so that one server isn't having to do everything.
Depending on what actions needs to be done on the server, find a quick way to verify that someone has been authenticated, but this could slow down your server if you don't have special hardware to better handle decryption of a token, for example.
You may also want to look at using NIO (http://tutorials.jenkov.com/java-nio/index.html), to better scale to a large number of connections.
Ideally, you would not want to have the malicious requests hit your application at all but rather intercept/drop the traffic before it reaches your application servers. This way your read clients will not encounter any issues e. g. with degraded performance while the attack is under way.
ServerFault may be a good place to ask, if you intend going down that road.
i have a java project, works as a server. when an instance of this project running, i can run another instance.
how can i avoid running of more than one instance on same java project at the same time?
(Stop the server when another instance is detected)
import java.net.ServerSocket;
.....
private static final int PORT = 9999;
private static ServerSocket socket;
public static void main(String[] args) {
try {
socket = new ServerSocket(PORT, 0, InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }));
{/*here write your own code taht must be run in the main*/}
} catch (BindException e) {
System.err.println("**********************************Already running.");
System.exit(1);
} catch (IOException e) {
System.err.println("************************************Unexpected error.");
e.printStackTrace();
System.exit(2);
} catch (Exception e) {
System.err.println("************************************ Error");
System.exit(3);
}
}
i used this code and it work try it
Easiest way is to use lock file, this causes problems if the app crashed. Try writing the pid into the lock file, you can check if that pid exists (although not natively maybe in a wrapper shell script).
If you are running server can you not check if a port is open, or better still maybe a jmx instance on a known port.
I totally support #vickirk - his approach allows the second "un-needed" instance of your server become "dormant" instead of simply terminating, i.e. periodically run to perform a check if the "active" instance is still actually active/present, and take over if it went down.
In the distrubuted case, if the requirement is to have a single server instance spanning multiple machines, the approach is still to find a common resource that can be locked, physically or logically. For that purpose, I personally use a control database table where an active process writes its PID and "heartbeat", and all others are checking for that "heartbeat" to be fairly recent, and become active if its not.
you can write simple command line script for app start - that check is server runs before actually run new instance. Just check url with wget for example...