benratti / javapns

Automatically exported from code.google.com/p/javapns
0 stars 0 forks source link

500 error Socket Closed #110

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
First, thank you for a such an incredibly helpful lib. Much appreciated.

System:
Running javapns in AWS Beanstalk. Tomcat v7, 64 bit. Micro instance.

Code:
    Boolean bDev = (environment.equals("PROD")) ? false : true; // error happens in PRODuction
    String certPass = (bDev) ? "password1" : "password2";
    String certPath = (bDev) ? "Certificates-DEV.p12" : "Certificates-PROD.p12";
    int threads = 30;
    StringTokenizer st = null;
        String token = null;
        String badge = null;
        String sound = null;

        /* Create the queue */ 
        PushQueue queue = Push.queue(getClass().getClassLoader().getResource(certPath).getPath(), certPass, !bDev, threads);
        queue.start();

    /* Prepare a simple payload to push */ 
    AmazonS3 s3Client = new AmazonS3Client(myCredentials);  
    GetObjectRequest getObjectRequest = new GetObjectRequest("iAPNS", noun+".csv");
    S3Object s3Object = s3Client.getObject(getObjectRequest);

        InputStreamReader fileSent = new InputStreamReader(s3Object.getObjectContent());
        BufferedReader reader = new BufferedReader(fileSent);
        String line = reader.readLine();
        while ( line != null ) 
        {   
            if (line.trim().equals("")) break; 

            st = new StringTokenizer(line, ",");
            while(st.hasMoreTokens())
            {
                token = st.nextToken();
                badge = st.nextToken();
                sound = st.nextToken();
            }

          queue.add(PushNotificationPayload.combined(message, Integer.parseInt(badge), (sound.equals("q.wav"))?null:sound), token);

            // move to next line
            line = reader.readLine();
        }

        reader.close();
        fileSent.close();

        queue.clearPushedNotifications(); 

Code reads token list from CSV file. Sample Data:
0039f5dbdf28e23512e8a7280e37dce7206c95a1c968aeb877a2f6c7234f8b02,5,t.wav
008066f4d95621e8654b81a37b4945f96c673dfdfea4869ebddc24592701bab9,5,t.wav
0083a705c24f27d86da0e00e7f60151404a811188fbdd2cecaa9fabb2d25190f,1,t.wav

Notes:
Smallest csv file has 2500 tokens. Largest has 130,000 and growing. Error 
occurs regardless to size but happens much more often in the larger files. Many 
times the smaller files do not throw an error. 

Feedback service is implemented but I can't rule out that it may be failing and 
introducing a token Apple rejects. However in that case is there a better way 
for me to write my code so I can limit the number of tokens that fail as a 
result? Any other coding tips or best practices are encouraged.

Error:
HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from 
fulfilling this request.

exception

org.apache.jasper.JasperException: An exception occurred processing JSP page 
/api2.jsp at line 113

110:            queue.add(PushNotificationPayload.combined(message, 
Integer.parseInt(badge), (sound.equals("q.wav"))?null:sound), token);
111:           
112:             // move to next line
113:             line = reader.readLine();
114:         }
115:         

Stacktrace:
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:567)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:461)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:389)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:333)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause

java.net.SocketException: Socket is closed
    sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1304)
    sun.security.ssl.AppInputStream.read(AppInputStream.java:84)
    org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:187)
    org.apache.http.impl.conn.LoggingSessionInputBuffer.read(LoggingSessionInputBuffer.java:82)
    org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:164)
    org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:138)
    sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:282)
    sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:324)
    sun.nio.cs.StreamDecoder.read(StreamDecoder.java:176)
    java.io.InputStreamReader.read(InputStreamReader.java:184)
    java.io.BufferedReader.fill(BufferedReader.java:153)
    java.io.BufferedReader.readLine(BufferedReader.java:316)
    java.io.BufferedReader.readLine(BufferedReader.java:379)
    org.apache.jsp.api2_jsp._jspService(api2_jsp.java:190)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:433)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:389)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:333)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

Thank you for your time considering the ticket.

Original issue reported on code.google.com by mooner...@gmail.com on 29 Feb 2012 at 1:15

GoogleCodeExporter commented 9 years ago
... and using javapns v2.2

Original comment by mooner...@gmail.com on 29 Feb 2012 at 1:19

GoogleCodeExporter commented 9 years ago
... and previously I was getting out of memory errors. Those errors have been 
replaced with the socket closed error above. Wondering if they were related I 
rebuilt the AWS instance since posting the ticket. A production push of 147,457 
tokens were all sent successfully in  231 seconds.  If the pattern repeats then 
I would expect that after one or two more sends the error will return. I then 
will have to rebuild or restart. It will work a couple times, then repeat. Hope 
that helps.

Original comment by mooner...@gmail.com on 29 Feb 2012 at 2:09

GoogleCodeExporter commented 9 years ago
... that didn't take long. The system one minute after posting my last message 
sent out another 147K messages but it failed due to the same error above. 
Rebuilding AWS Beanstalk again. Let's see if the pattern continues.

Original comment by mooner...@gmail.com on 29 Feb 2012 at 2:12

GoogleCodeExporter commented 9 years ago
Hi Mooner,

From the look of that stacktrace I'd say that the problem isn't with JavaPNS, 
it's with the S3 connection -- it's coming out of the call to reader.readline().

I haven't worked with the Amazon API; but my recommendation would be to read 
the entire csv file into memory in one hit, then process its contents.

Cheers,
Brian

Original comment by tho...@gmail.com on 29 Feb 2012 at 3:13

GoogleCodeExporter commented 9 years ago
Brian you might be onto something there. I have updated the code to put the 
file into an ArrayList var. Once that's complete it now loops over the 
ArrrayList and feeds the push queue. I will get results from this approach in 
about 12 hours. I will update the ticket with the code if successful or more 
details if it fails. Thanks much.

Original comment by mooner...@gmail.com on 29 Feb 2012 at 4:01

GoogleCodeExporter commented 9 years ago
Indeed, JavaPNS is not involved in the error you documented (it isn't even in 
the stack traces you provided).  It might take a long time to process all your 
notifications (you have a lot of them), and that could be why your server 
appears to encounter a timeout of some sort.

Unless JavaPNS appears in your stack traces, I think we could close this issue 
as unrelated to JavaPNS...

Original comment by sype...@gmail.com on 29 Feb 2012 at 3:30

GoogleCodeExporter commented 9 years ago
Happy to report been pushing notifications all day. Except for one connection 
failed, which I will assume is a AWS availability hiccup, we've been error 
free. Thank you again for pointing out way to the solution.

Below is the working code for anyone who may benefit from it:

AWSCredentials myCredentials = new BasicAWSCredentials("", "");

Boolean bDev = (environment.equals("PROD")) ? false : true;
String certPass = (bDev) ? "" : "";
String certPath = (bDev) ? "Certificates-DEV.p12" : "Certificates-PROD.p12";
int threads = 30;
StringTokenizer st = null;
String token = null;
String badge = null;
String sound = null;

AmazonS3 s3Client = new AmazonS3Client(myCredentials);  
GetObjectRequest getObjectRequest = new GetObjectRequest("iAPNS", noun+".csv");
S3Object s3Object = s3Client.getObject(getObjectRequest);

// GET TOKENS FROM FILE INTO VAR
int n = 0;
final class Token
{
    String tokenID;
    String badge;
    String sound;
}
    ArrayList<Token> TokenList = new ArrayList<Token>();

    InputStreamReader fileSent = new InputStreamReader(s3Object.getObjectContent());
    BufferedReader reader = new BufferedReader(fileSent);
    String line = reader.readLine();
    while ( line != null ) 
    {   
        if (line.trim().equals("")) break; // continue creates a loop

        st = new StringTokenizer(line, ",");
        while(st.hasMoreTokens())
        {
            Token t = new Token();
            t.tokenID = st.nextToken();
            t.badge = st.nextToken();
            t.sound = st.nextToken();
            TokenList.add(t);
        }
        n++;

        line = reader.readLine();
    }
    out.println("TokenList: " + n);

    reader.close();
    fileSent.close();

    /* Javapns QUEUE */ 
    PushQueue queue = Push.queue(getClass().getClassLoader().getResource(certPath).getPath(), certPass, !bDev, threads);
    queue.start();
    for (Token t : TokenList)
    {
        queue.add(PushNotificationPayload.combined(message, Integer.parseInt(t.badge), (t.sound.equals("q.wav"))?null:t.sound), t.tokenID);
    }
    queue.clearPushedNotifications(); 
    out.println("Queue Sent");

}

Thank you.

Original comment by mooner...@gmail.com on 1 Mar 2012 at 12:15

GoogleCodeExporter commented 9 years ago
Thank you!  Closing issue..

Original comment by sype...@gmail.com on 2 Mar 2012 at 2:20