You need to sign in to do that
Don't have an account?
Chirag Mehta
java.net.ProtocolException: Unexpected response 401: TransportExchange
I'm trying to build the "JavaClientExample" as described @ http://wiki.developerforce.com/index.php/Getting_Started_with_the_Force.com_Streaming_API
I am able to successfully connect to salesforce, but post that I get following error: (Any idea or help will be really appreciated)
Waiting for handshake 2011-10-20 11:29:24.779:INFO:org.cometd.client.BayeuxClient@229902: java.net.ProtocolException: Unexpected response 401: TransportExchange@21375057=POST//na1.salesforce.com:443/cometd/handshake#7 at org.cometd.client.BayeuxClient$PublishTransportListener.onProtocolError(BayeuxClient.java:969) at org.cometd.client.transport.LongPollingTransport$TransportExchange.onResponseComplete(LongPollingTransport.java:291) at org.eclipse.jetty.client.HttpExchange$Listener.onResponseComplete(HttpExchange.java:920) at org.eclipse.jetty.client.HttpExchange.setStatus(HttpExchange.java:263) at org.eclipse.jetty.client.HttpConnection$Handler.messageComplete(HttpConnection.java:622) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:862) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:214) at org.eclipse.jetty.client.HttpConnection.handle(HttpConnection.java:269) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:515) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:40) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:529) at java.lang.Thread.run(Unknown Source)
Changed the following lines in the original Java client code to get it up and running:
1. API version on the end point:
private static final String DEFAULT_PUSH_ENDPOINT = "/cometd/23.0";
2. Added '/topic/' to channel:
client.getChannel("/topic/" + topic).subscribe(new MessageListener() {
3. Change to include token as OAuth authorization header instead of cookie:
- final String sid = response.getString("access_token"); //Changed to final
- LongPollingTransport transport = new LongPollingTransport(
options, httpClient) {
@Override
protected void customize(ContentExchange exchange) {
super.customize(exchange);
exchange.addRequestHeader("Authorization", "OAuth " + sid);
}
};
/* BayeuxClient client = new BayeuxClient(instance_url
+ DEFAULT_PUSH_ENDPOINT, new LongPollingTransport(
options, httpClient));
client.setCookie("sid", sid, 24 * 60 * 60 * 1000);*/
BayeuxClient client = new BayeuxClient(instance_url + DEFAULT_PUSH_ENDPOINT, transport);
All Answers
I'm running into the same problem. I had a working program the last time i worked on it, which was during Dreamforce. I returned to it today and now I'm getting the same error.
Can you send us your orgids? Also, please provide login access so that we can examine your org.
Thanks!
Vinod.
org: 00DA0000000H0K7
access granted. Thanks
Organization ID 00D300000006hMb
Access granted to "Salesforce Support" for One Week.
Let me know if anything else is required.
Chirag, I used your sessionid to connect to streaming API and I was able to connect fine.I created few records in your org and I was able to see the streamed events.
Please make sure you have:
private static final String CHANNEL = "/topic/AllAccounts";
private static final String STREAMING_ENDPOINT_URI = "/cometd/23.0";
Also make sure the sessionId you are using is valid. To validate it go to:
https://na1.salesforce.com/soap/ajax/23.0/debugshell.html
set:
sforce.connection.sessionId = ".... <your sessionid> ...."
sforce.connection.getUserInfo(); -> this should give you the right output. If it fails with INVALID_SESSION_ID then your sessionid is not valid.
Kevin, I tried your org as well. I was able to connect just fine:
Running streaming client example....
Login successful!
Endpoint: https://<>.salesforce.com
Sessionid=.....
Waiting for handshake
[CHANNEL:META_HANDSHAKE]: {"id":"1","minimumVersion":"1.0","supportedConnectionTypes":["long-polling"],"successful":true,"channel":"/meta/handshake","clientId":"...........","version":"1.0"}
[CHANNEL:META_CONNECT]: {"id":"2","successful":true,"advice":{"interval":0,"reconnect":"retry","timeout":110000},"channel":"/meta/connect"}
Subscribing for channel: /topic/CaseQueued
Waiting for streamed data from salesforce ...
[CHANNEL:META_SUBSCRIBE]: {"id":"4","subscription":"/topic/CaseQueued","successful":true,"channel":"/meta/subscribe"}
[CHANNEL:META_CONNECT]: {"id":"3","successful":true,"channel":"/meta/connect"}
Please make sure the sessionid that is generated after login is valid (using the debug shell perhaps).
I can connect fine also using workbench, just can't in my java app.
I remember something was mentioned at dreamforce about some uri changing with this in winter 12. So it must have been the endpoint and topic. The java example on the wiki still has the old way to connect where the endpoint is just /cometd and the channel is just "/topicname"
http://wiki.developerforce.com/index.php/JavaClientExample.java
This JavaClientExample is outdated. Apologies for the confusion. We'll have it updated soon.
Here is the latest doc:
http://www.salesforce.com/us/developer/docs/api_streaming/index.htm
http://www.salesforce.com/us/developer/docs/api_streaming/api_streaming.pdf
The release notes are here: https://eu1.salesforce.com/help/doc/en/salesforce_winter12_release_notes.pdf
(page#103)
There are 3 important changes that you need to be aware of:
1. The sessionid / oauth token now needs to go with the Authorization header, instead of cookies (example: Authorization: OAuth <sessionId>)
2. API version is now required in the URL: example: https://instance.salesforce.com/cometd/23.0
3. topic names are now prefixed with "/topic" (example: /topic/AllAccounts)
Changed the following lines in the original Java client code to get it up and running:
1. API version on the end point:
private static final String DEFAULT_PUSH_ENDPOINT = "/cometd/23.0";
2. Added '/topic/' to channel:
client.getChannel("/topic/" + topic).subscribe(new MessageListener() {
3. Change to include token as OAuth authorization header instead of cookie:
- final String sid = response.getString("access_token"); //Changed to final
- LongPollingTransport transport = new LongPollingTransport(
options, httpClient) {
@Override
protected void customize(ContentExchange exchange) {
super.customize(exchange);
exchange.addRequestHeader("Authorization", "OAuth " + sid);
}
};
/* BayeuxClient client = new BayeuxClient(instance_url
+ DEFAULT_PUSH_ENDPOINT, new LongPollingTransport(
options, httpClient));
client.setCookie("sid", sid, 24 * 60 * 60 * 1000);*/
BayeuxClient client = new BayeuxClient(instance_url + DEFAULT_PUSH_ENDPOINT, transport);
Thanks a lot @VM_SFDC / @sgurumurthy. Finally the streaming worked for me.
To add more (@sgurumurthy : I had hard time executing 3rd point due to illegal characters, override annotation and few other things. For ease, below is the function that needs to be updated)
For the record - I just updated the Getting Started with the Force.com Streaming API article to reflect the changes in the Winter '12 release.
Cheers,
Pat
Seems the changes aren't saved -:)
The page says
There is currently no text in this page. You can search for this page title in other pages, search the related logs, or edit this page.
Oops - looks like some weird characters crept into the link - fixed now. Thanks, Chirag!
It's my pleasure too. Now it looks great and complete too. Thanks a lot!
I got it working again too. Thanks everyone
The message indicates authentication failure. So check if you have any inadvertent changes in any of the data fields. If not, will need to see your code section where the error is thrown.
Regards,
Shashi
Hi Chirag,
Are you setting up the env variables in Heroku like so:
IP range restrictions in your org?
I was able to get through. It was a typo (Pls don't shout, humans tend to do mistake :smileyhappy:)
@Command Line : (Executed "target\bin\webapp.bat"). Below debug shows that it's executing and waiting for streamed data from force.com to send information on creation of new case. It's working as desired.
However after uploading to Heroku and executing it via app url (http://floating-sunrise-3802.herokuapp.com/), it waits but the very next second it crashes out (Below debug is pulled after running "heroku logs" command). Any clue on why it's failing when executed from heroku webapp mode?
Any suggestions on below error?
When you configure a Heroku app as a web application, the embedded jetty webserver attempts to bind to a port defined by Heroku. This port number is available on $PORT environment variable. You can see the actual code in Main.java generated by Maven. It appears that something is going wrong here.
My first thought was that you have not defined a Procfile in the root of the application directory. I discounted that because the error indicates it is starting web app. Still, could you verify you have a Procfile in the root of the applicatio directory and it contains following code: web: sh target/bin/webapp.
Yes there's already a Procfile in root directory (I created that while creating project). I re-tried everything and it seems I was able to get through the Port error, but (as evil doesnt leave u soon) there's one more error:
When i execute heroku run "sh target/bin/SFDC" where SFDC is my java program, it throws following error:
And the heroku logs says
How about running the java app directly, with no 'sh' - heroku run target/bin/SFDC
There's the problem. The target of sh, i.e. target/bin/SFDC in this case, cannot be a Java class. It has to be a shell script which in turn executes the java program.
For example, in my shell program to run the Main.java program, the last statement in the shell script is as follows. There are many more statements in the shell script before this statement which set up the environment.
exec "$JAVACMD" $JAVA_OPTS \ $EXTRA_JVM_ARGUMENTS \ -classpath "$CLASSPATH" \ -Dapp.name="webapp" \ -Dapp.pid="$$" \ -Dapp.repo="$REPO" \ -Dbasedir="$BASEDIR" \ my.package..Main \ "$@"
Hope this makes it clear.
Regards,
Shashi
same result :(
I executed heroku run "target/bin/SFDC"
And the heroku logs :
SFDC in "target/bin/SFDC" is SFDC.bat and not SFDC java class (which is actually at target/classes/foo/SFDC.class)
Can you post the SFDC shell script as well as the SFDC.java files somewhere where I can have a look.
Regards,
Shashi
Might be if this helps - The SFDC.java program is "Salesforce Steaming API Program, which runs and wait for streamed data from force.com". Can that be an issue?
SFDC.bat
That could be. Essentially the server program needs to run as a daemon process so it is started up as a servlet or application context listener. What the application developer, i.e. you and me, need to do is to write a client program which subscribes to a channel and waits for messages on that channel. Is this what SFDC.java does?
The SFDC.java is http://wiki.developerforce.com/page/JavaClientExample.java
After creating PushTopic in Salesforce (using system log), I tried creating this JAVA application which can subscribe for updates.
PS : Salesforce Streaming API uses the Bayeux protocol to make a connection to the Streaming API, subscribing to topics via the long-polling transport over HTTP.
Chirag, it appears to be some Heroku configuration error which we are not able to debug. I would suggest you review the Heroku workbook for Java to make sure you have followed the instructions properly. Then systematically introduce System.out.println in your main method of SFDC.java. If you do not get the first print as well in the Heroku log, then you know that there is a Heroku configuration problem. Good Luck!
Regards,
Shashi
I followed each and every step as mentioned in java heroku book.
SFDC.java is executing without any errors as heroku logs shows following SOP's. But after printing all below it says "Error R13 (Attach error) -> Failed to attach to process" > so this sounds like Heorku is not allowing to run a listener.
Chirag,
Can you post your Procfile? I believe what's happening is that you're running your app as a web process. In other words, your procfile probably starts your process using something like:
web: sh target/bin/script.sh
Web processes are a special process type that expect incoming HTTP traffic. What that means is that you need to bind the process to the port number specified in $PORT. In other words, you need to start a web server as shown in this example: http://devcenter.heroku.com/articles/java
Assuming you are using a web process, you have a couple options: 1) Startup a web server that binds to $PORT and run your listener in that process, or 2) use a different process type, such as a worker.
A worker process does not expect to handle incoming traffic and you shouldn't see the 'attach to process' error (as far as I know). To use a worker process, replace the `web` in your Procfile with `worker`, e.g.:
worker: sh target/bin/script.sh
Then, make sure you scale the processes appropriately. For instance, `heroku scale web=0` and `heroku scale worker=1`.