JAXRS Server check status - java

I have created a JAXRS SERVER for some web services. The server is working just fine, but I need to add a new feature so that I can check the server status at any time. So if the server is up I should return a message like running,and if is down a message like down.
My implementation so far:
public class Server
{
public static void main( final String[] args )
{
final JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean();
final SubscriptionService subscriptionService =
new SubscriptionService( SubscriptionRepo.getRepo() );
final SystemService systemservice = new SystemService();
serverFactory.setResourceProvider(new SingletonResourceProvider(subscriptionService));
serverFactory.setResourceProvider(new SingletonResourceProvider(systemservice));
serverFactory.setAddress( "http://localhost:8888" );
serverFactory.setProvider( JacksonJsonProvider.class );
serverFactory.create();
}
}
I have also created a service class where I want to get the status:
public class SystemService
{
#GET
#Path("/systemstatus")
public Response getSystemStatus()
{
return Response.status( Status.OK.getStatusCode() );
}
}
I really have no idea how can I return a status if the system is running or not.
Can anyone help me with some ideas on how to check the server status?

Your quest kind of collapses on itself when you consider that you're trying to get a response from a web service, that's deployed on a non-responsive web server. How exactly do you envisage your web service getting the word out (by way of a coherent HTTP status, no less), that it's not reachable? How are you even going to get to it in the first place? When the container is down, your service is not in a position to return any meaningful message to the client
Stick to time-tested exception handling in the various flavours of the connection-related SocketException and possibly the HttpRetryException, in some cases. That's all you're going to get when your server is not up: some variety of SocketException. Your REST service has no power here.

Related

Run out of ports calling my webservice from an android app

I have an android app and a C# web service
I am hosting my web service on IIS Express - nothing fancy just set up the directories.
My android app go to the web service gets the data and then displays it on the screen and repeats this as fast as it can go.
After a while my android app will throw the following exception:
"SoapFault - faultcode: 'soap:Server' faultstring: 'Server was unable to process request. ---> No ports available in the range 10101 to 11100' faultactor: 'null' detail: org.kxml2.kdom.Node#41bdf340"
I have Googled around a bit and have not found anything that will help me.
I ran CurrPorts to watch the ports and it looks like every time the app calls the web service it is using a different port.
They all use port 80 but different remote ports.
The exception is being thrown on the following line of code
"SoapPrimitive response = (SoapPrimitive) _envelope.getResponse();"
If I run IISReset the app will go back to getting data again until sometime thereafter to get the exception mentioned above.
Here is the code for my web service which is just returning a comma separated string (it will do something more interesting just trying to get this working)
Web service code
[WebMethod]
public string GetDefaultResults()
{
return "100,1,0,125.987,124.993,117.904,116.038";
}
Here is the code that my android app uses to call the web service.
I create a new thread and have it call this method then get the string value split it on ',' then put it in a few different TextViews
public class WebService implements Runnable{
private static String NAMESPACE = "http://tempuri.org/";
private static String URL = "http://mymachine/mywebservice/service.asmx";
private static String SOAP_ACTION = "http://tempuri.org/";
private String _soapAndMethod;
private HttpTransportSE _androidHttpTransport;
private SoapSerializationEnvelope _envelope;
private String _methodName;
public WebService(String methodName) {
_methodName = methodName;
_soapAndMethod = SOAP_ACTION + _methodName;
SoapObject request = new SoapObject(NAMESPACE, methodName);
_envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
_envelope.dotNet = true;
_envelope.setOutputSoapObject(request);
_androidHttpTransport = new HttpTransportSE(URL);
}
#Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
}
public String InvokeWebService() {
String resTxt = null;
try {
_androidHttpTransport.call(_soapAndMethod, _envelope);
SoapPrimitive response = (SoapPrimitive) _envelope.getResponse();
resTxt = response.toString();
} catch (Exception e){
e.printStackTrace();
}
return resTxt;
}
}
Any help would be great. Thank you to those who do respond. Is there some setting in IIS I need to change? Is there something I missed in my code?
Additional information:
When the server is responding the webservice request IIS creates a process called w3wp.exe and it this process that is running out of ports.
Doing in a little digging and experimentation the Webservice gets newed up each call to "GetDefaultResults". Which leaves w3wp.exe in a Listening state and they never go away until the iisreset is run.
Some time later it uses the remaining ports available and starts throwing that exception.
Why is it not reusing the same webservice instead of creating a new one each time.
If that is not possible what code do I write in the Webservice to close the connection after it is finished. I put in a hack to cause it close after 5 seconds to see if that would work at least.
It does clean up w3wp.exe but after a short time I start getting this exception on the client.
"expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope (position:START_TAG #2:7 in java.io.InputStreamReader#41beb098) "
so this is not a work around but it helped me understand what the problem is a little better.
protected override void Dispose(bool disposing)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 5000;
timer.Elapsed += timer_Elapsed;
timer.Start();
base.Dispose(disposing);
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Environment.Exit(1);
}
Thanks for your help.
If you failed your first request, you might need to enable IIS Express to allow external connections. In your case, it looks like it only failed after running for a while.
In your question, I see that you
"go to the web service gets the data and then displays it on the screen and repeats this as fast as it can go.
did not call "close" on HttpTransportSE
You might be running out of local ports. Are you reusing the connection on all your requests? If not, try to close it when you are done.
My Webservice was referencing an api to get the values from then pass them over a webservice to the android app.
The problem was that every time the webservice was being called a new reference would be created to the api and after the request was sent it would never close out the port. As soon as I stopped referencing the api everything worked.
A cludge to get this to work is I had the webservice monitor a folder and send the data in the file that was last created. Then created another program to attach to the api and output the data to that folder. Not the most elegant solution but it works as a proof of concept for what I am doing.
Still not entirely sure why the Webservice was never closing the port and I am suspect that the Webservice could not dispose of the reference to the api but I am not really sure.

Tomcat 7 Servlet spawning a thread

I am writing a web app that I want to use to perform FTP tasks (downloads)
I have Apache FTPS server installed in Tomcat and a Java Client ready to initiate the transfers.
The client will be invoked by the Servlet.
For example:
http://laptop:8080/MyServlet?action=download&from=desktop&file=C:/home/fred/file.xml
Would tell the instance on my laptop to download file.xml from my desktop.
EDIT:
Apologies, I never made this very clear.
There will be an FTP server at both ends of this process. 1 on my remote laptop and 1 on my local desktop. So in a nutshell I am submitting an FTP 'get' request to the Servlet on the remote side. The Servlet then kicks off an FTP process to pull the file across.
My Servlet is all set to receive the GET parameters and do the work.
If the file is quite big then each request will take a long time to complete. I want the Servlet resources freed up as quickly as possible.
Ideally I'd like the following things to happen:
User to send URL to Servlet
Servlet to digest the URL and work out what file and where from etc...
Servlet to pass info to a Thread
Servlet to come back with an "In progress" message
Request completes
Thread is still working in the background downloading the file
At this time I'm not too concerned with the Servlet having knowledge of the success of the thread, I just need it to kick one off and forget about it. The FTP process will have separate logging elsewhere for any issues.
I am interested in the concept of creating a Threadpool in the WebApp and fetching a thread from there but again, all examples I've found are old and don't really cater for my level of understanding.
There are a few similar questions on StackOverflow with this being the most similar to what I am asking for but it just hints at something ExecutorService that I have no prior knowledge of. How would I set this up in a WebApp ?
What is recommended way for spawning threads from a servlet in Tomcat
For info,
I have researched this and have found a lot of incomplete examples that require a better understanding than I currently have, or hints towards what is required.
Also a lot of the examples I've read are a few years old, nothing recent. I'm hoping there might be a magical one-liner to do everything I need (doubtful) that has come about in the last year or so :)
I'm new to Threading concepts in Java, I understand Threading in general so appreciate any help you can offer me.
Trevor
I'm not sure I have really understood what you want ...
client server
send request (via HTTP) and wait for
HTTP response
analyse request and find file to send
... (processing)
send HTTP response (1) with ?
opens FTP connection (could not open it before)
receive FTP request (command connection)
send file (data connection)
file is received and saved locally
If the client side is a browser, it should be enough for the response (1) to be a redirect to an URL like ftp://host/path/to/file, because all major browsers know of the FTP protocal and are able to use it to download a file.
The problem is not on server side, you can easily spawn a thread that could acts as a FTP client or (probably harder) as a FTP server, but I cannot imagine better than a redirection on client side : the client has open a HTTP connection than cannot be used for a FTP transfert and it must open a new connection for the FTP request. As it is a new connection, how do you want it to be processed by the thread launched at previous step ? There is no notion of session in FTP and there's no easy way to identify the right request.
Edit per comment:
Ok, I appears that you just want to do defered processing on server after request completion. You have two ways of doing that :
as suggested by you tags, use a worker thread to do the job. Your servlet is plain Java and you can create a thread like you would do in any other Java application. If you are interested in getting later the result of the defered processing, you could give a reference the the session (or simply to a session attribute) to the thread where it will be able to put its advancement and/or completion status. This requires some more boiler plate code but is guaranteed to work (examples below)
you can close the HTTP connection before the servlet returns. It is not explicitely guaranteed per the official servlet specs, but I found it to work at least in tomcat 7. You will find more details on that on this other post Servlet - close connection but not method
Example using simple threads, and storing status in session :
public class ThreadedServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest hsr, HttpServletResponse hsr1) throws ServletException, IOException {
String fileName = null;
// preliminary work ...
Worker worker = new Worker(fileName);
final HttpSession session = hsr.getSession();
synchronized (session) {
List<Status> statuses = (List<Status>) session.getAttribute("statuses");
if (statuses == null) {
statuses = new ArrayList<Status>();
}
statuses.add(new Status(fileName));
}
Thread thr = new Thread(worker);
thr.start();
// write the response either directly or by forwarding to a JSP
}
public static class Status implements Serializable {
private String fileName;
private WStatus status;
public Status(String fileName) {
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public WStatus getStatus() {
return status;
}
public void setStatus(WStatus status) {
this.status = status;
}
}
public enum WStatus {
STARTED,
RUNNING,
COMPLETED
}
private static class Worker implements Runnable {
private String fileName;
private Status status;
public Worker(String fileName) {
this.fileName = fileName;
}
#Override
public void run() {
status.setStatus(WStatus.RUNNING);
// do your stuff ...
status.setStatus(WStatus.COMPLETED);
}
}
}

Dynamic BlazeDS endpoint configuration

I search for some help creating a web Flex application using BlazeDS and Java server with dynamic BlazeDS endpoint configuration.
First, I will try to explain my current situation.
I have a Flex 3.2 application that provides GUI of the application. From the ActionScript I call Java methods using BlazeDS. To access the BlazeDS I use a Config class that provides the endpoint as shown below (it is a constructor):
public function Config(): void {
if (_serviceUrl == null) {
try {
var browser: IBrowserManager = BrowserManager.getInstance();
browser.init();
var url: String = browser.url;
var host: String = mx.utils.URLUtil.getServerName(url);
var port: uint = mx.utils.URLUtil.getPort(url);
var parts: Array = url.split('/');
if (parts[2] == '') {
url = DEFAULT_URL;
Alert.show("Unable to determine server location, using default URL: " + DEFAULT_URL, "Connection error");
}
else {
url = parts[0] + '//' + parts[2] + '/' + parts[3] + '/messagebroker/amf';
}
_serviceUrl = url;
} catch (e: Error) {
Alert.show("Exception while trying to determine server location, using default URL: " + DEFAULT_URL, "Connection exception");
_serviceUrl = DEFAULT_URL;
}
}
}
The idea of the class is to determine the endpoint from the request URL. I use a Delegate class to call the remote methods using BlazeDS like the following:
{
import com.adobe.cairngorm.business.ServiceLocator;
import mx.rpc.IResponder;
import mx.rpc.remoting.RemoteObject;
public class AbstractRemoteDelegate
{
public function AbstractRemoteDelegate(responder:IResponder,serviceName:String)
{
_responder=responder;
_locator=ServiceLocator.getInstance();
_service=_locator.getRemoteObject(serviceName);
_service.showBusyCursor=true;
_service.endpoint = Config.instance.serviceUrl;
}
private var _responder:IResponder;
private var _locator:ServiceLocator;
private var _service:RemoteObject;
protected function send(operationName:String,... args:Array) : void {
_service.getOperation(operationName).send.apply(_service.getOperation(operationName),args).addResponder(_responder);
}
}
}
This approach actually works fine. However, I got across a situation where I can't use dynamically determined URL. In such a situation, I need a hard-coded URL in the Config.as file. And this is the problem. When trying to deploy the application to another server, I always need to rebuild the application with a new URL configuration in the ActionScript class Config.
Therefore I search for a way to define a static configuration for the Flex application to connect to a BlazeDS server. And the way to change such configuration without rebuilding the application so I can give the customer his own way to reconfigure and move the Flex application.
I thought about using a configuration file, but Flex runs on the client side and there is no configuration file!
I thought about using database configuration, but I don't have any database on the client side!
To sum up, I am looking for a way, how to get BlazeDS URL from a configuration to be able to change it without rebuilding the whole app.
Thanks for any useful suggestions.
EDIT: Revised the question to be more actual. I improved the way to determine the URL dynamically from the request URL, so it works now even for proxy server. However, my curiosity persists for the configuration of flex without rebuilding.
Here is an old example Blaze DS Service of mine which does basically the same as you did. It's just the string which needs to be created correctly. If the endpoint address is wrong, catch the error accordingly.
My project may currently not build because of Flexmojos ... I'm not able to test that yet.
Since it did not read you question properly, I misunderstood you: You can put a configuration file next to the SWF and load it via URLLoader or pass it via FlashVars. That should give you the freedom to pass the endpoint dynamically.

Using Metro, adding a MTOMFeature to client side causes a MIMEParsingException, why?

We have an MTOM-enabled web service that is published with Grails and the Metro 1.0.2 plugin:
#MTOM
#WebService(targetNamespace="http://com.domain")
class TestService {
#WebMethod
int uploadFile(#XmlMimeType("application/octet-stream")DataHandler data) {
data.dataSource.inputStream.eachLine {
println "reading: -> ${it}"
}
return 0
}
}
Following this tutorial, we set up a Java test-client that looks like this
public class Client {
public static void main(String[] argv) {
MTOMFeature feat = new MTOMFeature();
TestService service = new TestServiceService().getTestServicePort(feat);
Map<String, Object> ctxt = ((BindingProvider)service).getRequestContext();
ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
service.uploadFile(new DataHandler(new FileDataSource("c:/file.xml")));
}
}
When I run the client, I get the following error message:
Couldn't create SOAP message due to
exception:
org.jvnet.mimepull.MIMEParsingException:
Missing start boundary
However, when I don't add the MTOMFeature, and just do
TestService service = new TestServiceService().getTestServicePort(); the files gets uploaded ok. But as I understand it if MTOM is not enabled on both server and client side, the entire file will be kept in memory (and not streamed). So, my questions are
Why do we get that error?
If I don't add the MTOMFeature, will the file still be MTOM-transmitted?
I would be very grateful for any help/tips!
After some research and testing, the answers are:
The error is because grails adds its own filtering, including services. So, by excluding the services from being filtered like this static excludes = ["/services/*"] in UrlMappings.groovy, it works.
No. Without the MTOMFeature the file will just be treated as any other data in the request. That means being stored in the memory, thus causing problems for big files.

How to initiate chatting between two clients and two clients only, using applets and servlets?

I first need to apologize for my earlier questions. (You can check my profile for them)They seemed to ask more questions than give answers. Hence, I am laying down the actual question that started all them absurd questions.
I am trying to design a chat applet. Till now, I have coded the applet, servlet and communication between the applet and the servlet. The code in the servlet side is such that I was able to establish chatting between clients using the applets, but the code was more like a broadcast all feature, i.e. all clients would be chatting with each other. That was my first objective when I started designing the chat applet. The second step is chatting between only two specific users, much like any other chat application we have. So this was my idea for it:
I create an instance of the servlet that has the 'broadcast-all' code.
I then pass the address of this instance to the respective clients.
2 client applets use the address to then chat. Technically the code is 'broadcast-all', but since only 2 clients are connected to it, it gives the chatting between two clients feature. Thus, groups of 2 clients have different instances of the same servlet, and each instance handles chatting between two clients at a max.
However, as predicted, the idea didn't materialize!
I tried to create an instance of the servlet but the only solution for that was using sessions on the servlet side, and I don't know how to use this session for later communications.
I now know how to use the request.getSession(). So I set the session for an applet in its param tag and use it for further communications with the servlet. But how do I use this data to establish chatting between two clients? As I wrote earlier, I have the code for broadcast_all chatting as follows:
public class CustomerServlet extends HttpServlet {
public String getNextMessage() {
// Create a message sink to wait for a new message from the
// message source.
return new MessageSink().getNextMessage(source);
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ObjectOutputStream dout = new ObjectOutputStream(response.getOutputStream());
String recMSG = getNextMessage();
dout.writeObject(recMSG);
dout.flush();
}
public void broadcastMessage(String message) {
// Send the message to all the HTTP-connected clients by giving the
// message to the message source
source.sendMessage(message);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
ObjectInputStream din= new ObjectInputStream(request.getInputStream());
String message = (String)din.readObject();
ObjectOutputStream dout = new ObjectOutputStream(response.getOutputStream());
dout.writeObject("1");
dout.flush();
if (message != null) {
broadcastMessage(message);
}
// Set the status code to indicate there will be no response
response.setStatus(response.SC_NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
}
}
MessageSource source = new MessageSource();
}
class MessageSource extends Observable {
public void sendMessage(String message) {
setChanged();
notifyObservers(message);
}
}
class MessageSink implements Observer {
String message = null; // set by update() and read by getNextMessage()
// Called by the message source when it gets a new message
synchronized public void update(Observable o, Object arg) {
// Get the new message
message = (String)arg;
// Wake up our waiting thread
notify();
}
// Gets the next message sent out from the message source
synchronized public String getNextMessage(MessageSource source) {
// Tell source we want to be told about new messages
source.addObserver(this);
// Wait until our update() method receives a message
while (message == null) {
try {
wait();
} catch (Exception e) {
System.out.println("Exception has occured! ERR ERR ERR");
}
}
// Tell source to stop telling us about new messages
source.deleteObserver(this);
// Now return the message we received
// But first set the message instance variable to null
// so update() and getNextMessage() can be called again.
String messageCopy = message;
message = null;
return messageCopy;
}
}
On the applet side, I have a thread that will connect to the servlet above using GET method to get new messages. It uses a while loop, and blocks until it gets a message from the servlet. The main thread communicates with the servlet using POST method whenever the client has entered the message. Currently all clients chat with everyone. I want to use the same methods used above (or if possible any other way) to establish chatting between two clients and two clients only. I could possibly have another thread in the applet to check if any other user wishes to chat with it and then exchange some data so that only those two user chat...
I then tried to modify my broadcast-all code. In that code, I was using classes that implemented Observer and Observable interfaces. So the next idea that I got was:
Create a new object of the Observable class(say class_1). This object be common to 2 clients.
2 clients that wish to chat will use same object of the class_1.
2 other clients will use a different object of class_1.
But the problem here lies with the class that implements the Observer interface(say class_2). Since this has observers monitoring the same type of class, namely class_1, how do I establish an observer monitoring one object of class_1 and another observer monitoring another object of the same class class_1 (Because notifyObservers() would notify all the observers and I can't assign a particular observer to a particular object)?
I first decided to ask individual problems, like how to create instances of servlets, using objects of observable and observer and so on in stackoverflow... but I got confused even more. Can anyone give me an idea how to establish chatting between two clients only?(I am using Http and not sockets or RMI).
Regards,
Mithun.
P.S. Thanks to all who replied to my previous (absurd) queries. I should have stated the purpose earlier so that you guys could help me better.
You need to store all connected users in a Map<String, User> in the application scope using ServletContext#setAttribute(). The String denotes the unique user identifier (chat nickname?). You need to store the specific chat User as well in the session scope using HttpSession#setAttribute(). You also need to store the other user in individual chats in a Map<String, User> in the session scope of the users in question. You can obtain the attribute by the getAttribute() method.
This way you know which users are all available and which user is in the current session and with which users it is individually chatting.
This is a crude way to do it, but I just couldn't find a feasible solution. What I did was that I made all users connect to the servlet that had the broadcastAll code. Each user would be aware of which other user it is chatting with. Hence, while sending a message, the user would append his name and the name of the user that he is chatting with to the message. Since it is a broadcastAll code, every connected user would receive the message. After receiving the message, the user would parse the message to get the user who sent the message, and the name of the user for whom the message was intended. It would compare these two names with its records - see the statement in bold earlier. If matched it would display the message, else ignore it.
Again, its a crude way to do it and I am sure there are better solution out there.

Categories