Health check servlet doesn't establish connection? - java

I'm trying to write a bare-bones health check servlet for my app, just to see if my Tomcat server is running. Essentially, it's a servlet with a "/health" endpoint that is an empty page. Below is my code:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class HealthCheckServlet extends HttpServlet
{
private static final String SUCCESS = "Success";
private static final String FAILURE = "Failure";
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
isConnectionOK(request);
}
private static String isConnectionOK(HttpServletRequest request) throws IOException
{
String status = "";
try
{
URL connectionURL = new URL(request.getRequestURL().toString() + "/health");
HttpURLConnection connection = (HttpURLConnection) connectionURL.openConnection();
connection.setRequestMethod("GET");
connection.connect();
int httpResponseCode = connection.getResponseCode();
if (httpResponseCode == 200)
{
status = SUCCESS;
}
}
catch (IOException e)
{
status = FAILURE;
}
return status;
}
}
When I navigate to localhost:8080/health and debug it, it reaches my breakpoint at URL connectionURL = new URL(request.getRequestURL().toString() + "/health"); but won't progress to any subsequent breakpoints. The page itself returns a status code of 200, so I'm just trying to get the code to pick up on that.
Am I doing something wrong with trying to establish this connection within a servlet, or is there another problem here?

Related

Scheduled task through annotations in servlet is not working

I have a server that handles requests, and with regular intervals (every 1-2 minutes) needs to call another server and update a list of objects that is used to create the response to the request. Inspired by for example the accepted answer for this question, I tried to use the Schedule annotation, but can't get it to work.
How to run a background task in a servlet based web application?
A simplified view of the server is:
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(name = "MyServer", urlPatterns = {"/data/*", "/scheduled/*"}, loadOnStartup = 1)
public class MyServlet extends HttpServlet {
private static final String UTF_8 = "UTF-8";
private static final String APPLICATION_JSON = "application/json";
private static final long serialVersionUID = 1L;
private static connector connector;
public MyServlet() {
super();
}
public void destroy() {}
#Override
public void init() throws ServletException {
connector = new connector();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getServletPath();
String pathInfo = request.getPathInfo().substring(1);
response.setContentType(APPLICATION_JSON);
response.setCharacterEncoding(UTF_8);
if (path.endsWith("/data")) {
List<DataItem> dataItems = connector.currentData;
response.getWriter().write(JsonUtility.convertToJsonString(dataItems));
} else if (path.endsWith("/scheduled")) {
connector.fetchData();
response.getWriter().write("Done");
} else {
response.getWriter()
.write(pathInfo + " Is not Found but not returning 404");
return;
}
}
}
The connector class that is supposed to update the stored data from the other server at regular intervals is:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
#Startup
#Singleton
public class Connector {
public List<DataItem> currentData = new LinkedList<>();
#Lock(LockType.READ)
#Schedule(second = "*", minute = "*/2", hour = "*", persistent = false)
public void fetchNews() {
logger.debug("Fetching data");
String response = sendGet(url, bearerToken);
JsonObject json = new Gson().fromJson(response, JsonObject.class);
//Transform the response to a list of DataItems.
List<DataItem> retrievedData = toDataList(json)
System.out.println(retrievedData);
synchronized(currentData) {
currentData = retrievedData;
}
}
private String sendGet(String path, String authorizationProperty) {
URL url;
try {
url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", authorizationProperty);
conn.setRequestProperty("Content-Type","application/json");
conn.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String output;
StringBuffer response = new StringBuffer();
while ((output = in.readLine()) != null) {
response.append(output);
}
in.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
However, the method fetchData is not firing every second minute as I was expecting. I don't know what I am missing. I have played around a bit with adding/removing the #Startup annotation, creating an instance of the class in the init() method on the server, but still have no result.

Servlet for receive and share streaming data

I have three programs (a-b-c): a starts b that handles c, when c ends a restarts b. I can only change b, but it is unstable because it is restarted. I was thinking of solving my problems with a servlet service that receives b data and errors and displays them on a web page immediately. I tried two ways: 1. Receive data in a Thread parallel to the servlet and share it with it (I did not succeed); 2. Receive data from a client and share it with ServletContext and refresh the page with sent event but skip lines, even with retry: 100, and repeat the last one when there are no new data. Is there a way to send data to all servlet clients only when they are new? Is there a better solution considering that b is restarted and that I have to limit the ports used?
--UPDATE--
Servlet.java
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
#WebServlet(name = "Servlet", urlPatterns = {"/Servlet", "/test"})
public class Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("Connection", "keep-alive");
response.setContentType("text/event-stream");
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache");
String datain = request.getParameter("StringIn");
String dataold = request.getParameter("StringOld");
PrintWriter writer = response.getWriter();
if (datain == null) {
boolean test = getServletContext().getAttribute("actualData").equals(request.getParameter("StringOld"));
if (!test) {
writer.write("data: " + getServletContext().getAttribute("actualData") +"\n\n");
writer.write("retry: 500");
}
else {
writer.write("data: \n\n");
writer.write("retry: 1000");
}
}
else {
getServletContext().setAttribute("actualData", datain);
writer.write("data receive!\n\n");
}
writer.flush();
writer.close();
}
}
Script index.jsp
var eventSource = null;
var oldmessage = "";
var path = "http://localhost:8080/Servlet?StringaOld=";
function start() {
eventSource = new EventSource(path + oldmessage);
eventSource.onopen = function () {
};
eventSource.onmessage = function (message) {
var mex = message.data;
message.data = null;
if (mex != null) {
oldmex = mex;
testo.value += mex + "\n";
}
};
eventSource.onerror = function (error) {
eventSource = new EventSource(path + encodeURI(oldmessage));
};
Start.disabled = true;
}
function stop() {
eventSource.close();
Start.disabled = false;
}

request.getParameter() returns null but data can read from request.getInputStream() for huge data in http post method

I am having an issue where calling request.getParameter() returns null when large amounts of data are passed to the page. The header Content-Type is application/x-www-form-urlencoded. And the setting for maximum POST size is set to 12,582,912 bytes (i.e. maxPostSize=12582912) in server.xml.
Client Code
public class Send
{
public static int readTimeout = 30000;
public static int connectionTimeout = 10000;
public static void main(String[] args) throws IOException, JSONException
{
sendFile(1000,1);
}
public static void sendFile(int n,int m) throws IOException, JSONException
{
String urlStr = "http://localhost:8080/sendChange";
URL url = new URL(urlStr);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setConnectTimeout(connectionTimeout);
httpConn.setReadTimeout(readTimeout);
httpConn.setRequestMethod("POST");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
JSONArray list;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < m; i++)
{
list = new JSONArray();
for (int j = 0; j < n; j++)
{
list.put(getChange());
}
if(i==0)
{
stringBuilder.append("bulk=");
}
else
{
stringBuilder.append("&bulk_").append(i).append("=");
}
stringBuilder.append(list.toString());
}
int length = stringBuilder.toString().getBytes().length;
System.out.println(length);
httpConn.setRequestProperty("Content-Length", Integer.toString(stringBuilder.toString().getBytes().length));
DataOutputStream printout = new DataOutputStream(httpConn.getOutputStream());
printout.write(stringBuilder.toString().getBytes());
printout.close();
int responseCode = httpConn.getResponseCode();
System.out.println(responseCode);
}
Server Code
import org.json.JSONArray;
import org.json.JSONException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by mohan-4019 on 12/28/16.
*/
#WebServlet(name = "CollectorServlet")
public class CollectorServlet extends HttpServlet
{
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
{
String bulk = request.getParameter("bulk");
try
{
JSONArray bulkJSON = new JSONArray(bulk);
int length = bulkJSON.length();
}
catch (JSONException e)
{
System.out.println(e);
}
}
}
The call to getChange() returns a JSONObject, which has size 7kb.
It works perfectly for data with small size.
Large data can read from request.getInputStream().

Printing string array stored data on screen in (servlets)

I'm learning about servlets in java. Bellow is my code that is suppose to get the content of the url, store it in array list and, display it on the screen. for some reason I'm unable to get the string array content to displayed on the screen. When I load the page I get the "no luck" message. Any ideas why? thanks
//package fortune;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static java.util.Arrays.*;
import java.util.Collections;
import java.util.List;
#WebServlet(name = "FortuneServlet", urlPatterns = {"/"})
public class FortuneServlet extends HttpServlet {
//private String [] cookies = null;
List<String> cookies = new ArrayList<>();
String line ;
public void geturl(String[] args) {
try
{
URL url = new URL(" http://fortunes.cat-v.org/openbsd/");
//URL url = new URL(" http://bbc.com");
// read text returned by server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
while((line = in.readLine()) != null)
{
cookies.add(line);
//line = in.readLine();
}
in.close();
}
catch (java.net.MalformedURLException e) {
System.out.println("Malformed URL: " + e.getMessage());
}
catch (IOException e) {
System.out.println("I/O Error: " + e.getMessage());
}
}
public void init() throws ServletException {
}
#Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/plain");
if (cookies != null)
{
//response.getWriter().println(
// cookies[new Random().nextInt(cookies.length)]
//);
for (String str: cookies)
{
Collections.shuffle(cookies);
response.getWriter().println(str);
}
}
else {
response.getWriter().println("No luck!");
}
}
}
cookies is always an empty list (unless you are not showing something to us), so you always shuffle it and try to display, but because you don't have anything there you see a blank page.
I would change check cookies != null to !cookies.isEmpty().
EDIT:
You are not adding anything to the cookies list, so it is empty (List<String> cookies = new ArrayList<>();).
Maybe you wanted to call geturl (which does some add on the cookies list) method somewhere in the doGet? Right now it is not used anywhere.

Getting the roles of a user in wso2

I've created users and assigned them different roles using wso2im. Using these I managed to restrict access to a .jsp file so roles seem to be working right.
The problem lies when I need to display different things to different roles within the same JSP (For instance, role AAA can do xxx and yyy, role BBB can do zzz), I'm trying to check for roles using request.isUserInRole("role") but it always returns null, both when trying from the .jsp itself and the servlet that handles authentication.
Finally managed to get it to work. Getting the roles with the servlet and storing them in a cookie. Neither safe nor pretty but does the job:
package foo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.axis2.client.Options;
import org.apache.axis2.transport.http.HTTPConstants;
import org.wso2.carbon.um.ws.api.stub.RemoteUserStoreManagerServiceStub;
/**
* Servlet implementation class LoginServlet
*/
#WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private final String basicAuthUserID = "admin";
private final String basicAuthPassword = "admin";
private final String serverUrl = "https://localhost:9444/services/";
private RemoteUserStoreManagerServiceStub stub = null;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// get request parameters for userID and password
String user = request.getParameter("user");
String pwd = request.getParameter("pwd");
try {
if(authenticate(user,pwd)){
HttpSession session = request.getSession();
session.setAttribute("user", user);
//setting session to expiry in 30 mins
session.setMaxInactiveInterval(30*60);
Cookie userName = new Cookie("user", user);
userName.setMaxAge(30*60);
String[] roles = getRoleListOfUser(user);
String rolesTodos = null;
for (String s: roles){
if (!s.equals("Internal/everyone")) {
if (rolesTodos == null){
rolesTodos = s;
} else {
//System.out.println("Rol: " + s);
rolesTodos = rolesTodos + "," + s;
}
}
}
//System.out.println("Roles: " + rolesTodos);
Cookie rolesCookie = new Cookie("roles", rolesTodos);
rolesCookie.setMaxAge(30*60);
response.addCookie(userName);
response.addCookie(rolesCookie);
response.sendRedirect("index.jsp");
}else{
RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");
PrintWriter out= response.getWriter();
out.println("<font color=red>Either user name or password is wrong.</font>");
rd.include(request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean authenticate(String userName, Object credential) throws Exception {
if (!(credential instanceof String)) {
throw new Exception("Unsupported type of password");
}
try {
if(stub == null) {
stub = new RemoteUserStoreManagerServiceStub(null, serverUrl
+ "RemoteUserStoreManagerService");
HttpTransportProperties.Authenticator basicAuth = new HttpTransportProperties.Authenticator();
basicAuth.setUsername(basicAuthUserID);
basicAuth.setPassword(basicAuthPassword);
basicAuth.setPreemptiveAuthentication(true);
final Options clientOptions = stub._getServiceClient().getOptions();
clientOptions.setProperty(HTTPConstants.AUTHENTICATE, basicAuth);
stub._getServiceClient().setOptions(clientOptions);
}
return stub.authenticate(userName, (String) credential);
} catch (Exception e) {
handleException(e.getMessage(), e);
}
return false;
}
private String[] handleException(String msg, Exception e) throws Exception {
System.out.println(e.getMessage() + e);
throw new Exception(msg, e);
}
public String[] getRoleListOfUser(String userName) throws Exception {
try {
return stub.getRoleListOfUser(userName);
} catch (Exception e) {
System.out.println(e.getMessage() + e);
}
return null;
}
}

Categories

Resources