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.
Related
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.
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);
}
}
}
I have a project published in the Internet that is used by thousands of users every day. Basically, I'm using a server in AmazonAWS with the server part compiled in Java 6 running in a Tomcat. I'm using AMF to publish the services and my client is built in Flex 4.6 using Flash Builder to generate the classes to connect to the AMF services. The code I'm using to connect to the services is this:
public var cpcService:RemotingServicesImpl;
private function callService():void
{
FlexGlobals.topLevelApplication.callingService=true;
encryptedSession=ResourcesUtil.buildSessionId(globalSettings.sessionId, globalSettings);
var responder:Responder=new Responder(gameStateLoaded, gameStateFailed);
var token:AsyncToken=cpcService.getGameState(encryptedSession, taskKey);
token.addResponder(responder);
}
private function gameStateFailed(ev:FaultEvent=null):void
{
DisplayUtil.trackErrorInfoEvent("FATAL - FatalError", "getGameState-" + FlexGlobals.topLevelApplication.mainView.currentState, ev, encryptedSession);
}
private function gameStateLoaded(ev:Object):void
{
// my fantastic code when everything is ok
}
Normally, everything is ok and my application is working, but some calls (like 1 every 500) are not working, I know it because in the trackErrorInfoEvent function I'm registering an event in the Google Analytics, so I know this is randomly happening. This is the error:
faultCode = "Client.Error.MessageSend"
faultDetail = "Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed: url: 'https://appcog.cognifit.com/messagebroker/amf'"
faultString = "Send failed"
rootCause = (null)
Of course the URL is correct and is working all times.
I have seen in some blogs that adding this line:
<add-no-cache-headers>false</add-no-cache-headers>
the problem is fixed, but I have that line in my config file and is still happening.
I have checked my server logs and I have no records for service interruptions at any time.
I really apreciate any help, thanks in advance!
I have asked variations of this question over the past couple of days. I am not understanding or making the proper connections etc. so I am getting really frustrated not understanding which path I should be on.
I have developed a XAMLX WCF workflow service and my windows clients interact with it just fine. I am new to android and java and thus basically a NOOB. My service uses BasicHttpBinding and expects a couple of string values (uid & pwd) in the request. The response is simply a string.
Now on the android I am totally lost. I have read to use the AsyncTask, I've heard it has major issues and to use RoboSpice. Looking at RoboSpice it looks very solid but very stiff learning curve. I've heard for the stiff learning curve to use LoopJ as it will be easier when starting out. Throw in there the people who want you to use JSON and yeah. I'm definitely lost.
So I have been pulled in a lot of different directions. I know that I need it to be Async so it doesn't lock the ui thread and I would like to get to a solid robust solution but for now a baby step of just interacting with the service even synchronously would be encouraging.
Here are my basics:
Send a request to the service.
Have the application pause/loop etc. A progress bar would be wonderful but a simple loop that doesn't hang would be just fine for now.
RX the response and continue processing.
This is so simple for me in .NET I thought it would be simple. Just goes to show that pride cometh before the fall.
TIA
JB
Direct Question
As has been commented there are several implied questions in my OP. That is because I don't know what to ask. So let's go with AsynchTask for now. Let's call that my baby step.
Here are my questions:
HOW do I associate values to populate the request? In .NET I would create an object that matches what the request expects. So my object would have a UserName property and Password property. I would assign them their values like obj.UserName = "Joe"; I would then call the service operation and pass it obj.
HOW do I ensure I am using the proper libraries? I have read that AsyncTask uses the Apache Http Client library. OK I google that to get the jar's and apparently it's end of life. But still available so I download the latest and put it in my lib folder....but I didn't have to because I can import org.apache.http.HttpResponse without it so which version am I using then and should I use an older one or the latest.
**Finally how do I get the app to pause because this code does something (although it never shows in the logs of my service machine) and while it is off doing something my code continues to execute and crashes when it reaches the point where it needs the data from the service.....but it's not there. A progress bar would be the bees knees.
Here is my code for the implementation:
public class AsyncHttpRequestManager extends AsyncTask<String, Boolean, String>
{
private static final String serviceUrl = "http://www.serviceurl.com/service.xamlx";
#Override
protected String doInBackground(String... params)
{
try
{
DefaultHttpClient client = new DefaultHttpClient();
HttpPut putRequest = new HttpPut(serviceUrl);
putRequest.setHeader("Content-type", "text/plain");
putRequest.setHeader("Accept", "text/plain");
putRequest.setEntity(new StringEntity(params[0])); //This one is connected to my first question. How do I get the proper associations for the operations contract.
HttpResponse response = client.execute(putRequest);
InputStream content = response.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String result = "";
String s = "";
while ((s = buffer.readLine()) != null)
{
result += s;
}
return result;
}
catch (UnsupportedEncodingException e)
{
Log.e("AsyncOperationFailed", e.getMessage());
e.printStackTrace();
} catch (ClientProtocolException e)
{
Log.e("AsyncOperationFailed", e.getMessage());
e.printStackTrace();
} catch (IOException e)
{
Log.e("AsyncOperationFailed", e.getMessage());
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result)
{
Log.d("MESSAGE", result);
}
}
I call this like this:
new AsyncHttpRequestManager().execute("joe","asdf");
If more info is needed I will gladly post.
You should ask one question at a time, it's how SO is designed, and curated, to work.
For HTTP authentication
http://developer.android.com/reference/org/apache/http/auth/UsernamePasswordCredentials.html
E.g.
HttpClient client = new HttpClient();
client.getParams().setAuthenticationPreemptive(true);
Credentials defaultcreds = new UsernamePasswordCredentials("username", "password");
client.getState().setCredentials(new AuthScope("myhost", 80, AuthScope.ANY_REALM), defaultcreds);
Asynctask does not require any external libraries it's part of the Android platform. Don't get confused about HTTPClient and Asynctask. Asyntask is a generic class intended to call background processing on a separate thread from the main UI thread to avoid blocking. It just so happens that you are considering using an Asynctask to process your web request but they are not linked in any way.
Your question about "how to return data to my app" is best posed separately but, in essence, you're thinking sequentially. Your app should not pause. There are many methods, progress dialogs being one, to properly handle this.
Wrote a 'webservice' with Netbeans wizard, runs on glassfish. I added a reference using the wsdl to my .NET client, VB if it makes any difference.
I clearly have no idea what is going on, as I am encountering some brick walls.
The issue is a SoapHeaderException.
System.Web.Services.Protocols.SoapHeaderException: com/mysql/jdbc/Connection
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(
SoapClientMessage message, WebResponse response, Stream responseStream,
Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(
String methodName, Object[] parameters)
at WSClient.WSClient.localhost.DatabaseGateService.createCustomerTable(String xml)
in C:\Project\WSClient\Web References\localhost\Reference.vb:line 40
at WSClient.USAHWSClientConsumer.TestCustomer() in
C:\Project\WSClient\Client\WSConsumer.vb:line 22
The web service itself is simple:
#WebService()
public class DatabaseGate {
private MySQLManagerImp manager;
public DatabaseGate(){
manager = new MySQLManagerImp();
}
#WebMethod(operationName = "createCustomerTable")
public void createCustomerTable(#WebParam(name = "xml") String xml) {
manager.createCustomersTable(xml);
}
}
It takes an xml string, as I did not want to pass in an abomination of arguments.
I attempt to consume the service by simply instantiating the web reference:
Dim ws As localhost.DatabaseWS = New localhost.DatabaseWS
// Create the xml string
Dim qbCustomerQueryRS As String = qbQuery.GetCustomerQueryXML()
Dim processedCustomerXML As String =
customerResponseParser.GetAllCustomerDatabaseFriendlyXML(qbCustomerQueryRS)
ws.createCustomerTable(processedCustomerXML)
I've tried writing the string in a soap envelope, but still receive the same message. So passing a string is kaputt, as it should be; why would the WS know to parse a string, and simply instantiating and calling the method from the object as if it were local isn't working the way I think it does.
What is happening?
Sounds like the WSDL references com/mysql/jdbc/Connection, which is not a class known on the .NET side. If you have control over the Web Service, add annotations to avoid serialization of external class references (like com/mysql/jdbc/Connection). If you don't, simply download the WSDL to a text file, edit it manually to remove such classes/attributes, and re-create the reference pointing to the edited file. You can change the endpoints in Web.config later.
As it turns out, the reason I was receiving
System.Web.Services.Protocols.SoapHeaderException: com/mysql/jdbc/Connection
was similar to Diego's answer (thank you for pointing me in the right direction): A reference problem.
I assumed my WS deployment worked correctly because I had tested the method that executed, but only assuming the data I needed successfully transmitted over the wire.
Testing another angle using glassfish revealed:
Service invocation threw an exception with message : null; Refer to the server log for more details
Checking the server log, the answer was obvious:
java.lang.NoClassDefFoundError: com/mysql/jdbc/Connection
I had forgotten to add the jar to com/mysql/jdbc/Connection.