Reputation: 63
I'm coding a module for sending push notifications to IOS device using APNs using its new HTTP provider API.But I'm facing certain issues in the process of reading output from the response.Its throwing a invalid http response error.The following is the piece of code I have written :
static SSLSocketFactory getSSLSocketFactory() {
try {
String keystoreFilename = "D:/Oracle/IDCS/MFA/APNS/OMA_prereqs/iOS_prod.p12";
char[] storepass = "welcome1".toCharArray();
FileInputStream fis = new FileInputStream(
new File(keystoreFilename));
final KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(fis, storepass);
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("SunX509");
keyManagerFactory.init(ks, storepass);
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance("SunX509");
trustManagerFactory.init((KeyStore) null);
// trustManagerFactory.init(ks);
// create ssl context
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
// setup the HTTPS context and parameters
sslContext.init(keyManagerFactory.getKeyManagers(),
trustManagerFactory.getTrustManagers(), null);
if (keyManagerFactory != null || trustManagerFactory != null) {
return SSLTunnelSocketFactory.wrap(proxy,
sslContext.getSocketFactory());
}
} catch (Exception e) {
System.out.println("Unable to create ssl socket factory");
e.printStackTrace();
}
return HttpsURLConnection.getDefaultSSLSocketFactory();
}
private static void sendSamplePushNotification() {
System.setProperty("javax.net.debug", "all");
URL url = null;
try {
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};
JSONObject payload = new JSONObject();
JSONObject msg = new JSONObject();
try {
msg.put("alert", "Hello APNS");
payload.put("aps", msg);
} catch (JSONException e) {
e.printStackTrace();
}
url = new URL(
"https://api.development.push.apple.com:443/3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0");
HttpsURLConnection conn = (HttpsURLConnection) url
.openConnection(proxy);
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setHostnameVerifier(hv);
conn.setSSLSocketFactory(getSSLSocketFactory());
/*conn.setRequestProperty("content-length", new String(payload
.toString().getBytes()));*/
conn.setConnectTimeout(3000);
conn.connect();
OutputStream os = conn.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(writer);
bw.write(payload.toString());
bw.flush();
//System.out.println("Response code : " + conn.getResponseCode());
System.out.println(conn.getResponseMessage());
InputStream is = conn.getInputStream();
................
}
I'm getting the following exceptions on executing this :
.............................
...............................
main, WRITE: TLSv1.2 Alert, length = 26
[Raw write]: length = 31
0000: 15 03 03 00 1A 00 00 00 00 00 00 00 04 75 ED 66 .............u.f
0010: D6 88 EC E2 B4 8F FF A2 7E CC 1C 22 FF A7 EF ..........."...
main, called closeSocket(true)
null
java.io.IOException: Invalid Http response
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1889)
at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1884)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1883)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1456)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at com.coding.mfa.apns.driver.APNSDriver.sendSamplePushNotification(APNSDriver.java:141)
at com.coding.mfa.apns.driver.APNSDriver.main(APNSDriver.java:38)
Caused by: java.io.IOException: Invalid Http response
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1554)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at java.net.HttpURLConnection.getResponseMessage(HttpURLConnection.java:546)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseMessage(HttpsURLConnectionImpl.java:382)
at com.coding.mfa.apns.driver.APNSDriver.sendSamplePushNotification(APNSDriver.java:140)
... 1 more
Can someone please help me out? The SSL Handshake seems to be fine.Its failing at the line 'conn.getInputStream()'
Upvotes: 1
Views: 1054
Reputation: 11
From "APNs Provider API" documentation: "This API is based on the HTTP/2 network protocol". Java does not support HTTP/2 for now. It is expected Java 9 bring support for HTTP/2. You need use a thirdpart http client, here are sugestions: Does Apache or some other CLIENT JAVA implementation support HTTP/2?
Upvotes: 1
Reputation: 1741
First of all, I added the comment in my role as reviewer of new questions. The stack trace increases the chance someone would figure it out.
Second, it would help if you would pinpoint the line that causes the crash, as the stack trace doesn't list your code (maybe the 1 more?). Note that unlike null pointer, invalid HTTP response isn't necessarily a problem with your code. Which leads me to...
Third, and the reason I'm writing this as an answer, with Java it could be cookies. Try:
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
Fourth, if all else fails, you need to figure out the difference between postman and whatever's coming out of the java code. wireshark or a similar tool would probably do the trick.
Update: This post on SuperUser seems to indicate Java 7 disables TLS1.2 by default.
I see you're sending TLS1.2. If you're using Java 7, it seems there's a bug affecting updates 25 and above.
Upvotes: 0