I'm trying to develop a simple Java PubSubHubBub application. I downloaded this sample code to test it, but when I try to subscribe I always get an error 409.
Following PuSH specifications, I created my own feed at this link: receivetemplate.eu01.aws.af.cm/feed/
This is the code in the Test class for the subscriber:
package sub;
import java.net.InetAddress;
import PubSubHubbub.Web;
import PubSubHubbub.Subscriber;
public class Test {
private static Web webserver;
private static Subscriber sbcbr;
private static String hostname = null;
private static Integer webserverPort = 8080;
private static void startServer(){
try {
webserver = new Web(webserverPort);
sbcbr = new Subscriber(webserver);
InetAddress addr = InetAddress.getByName("receivetemplate.eu01.aws.af.cm");
hostname = addr.getHostName();
System.out.println("http://" + hostname + "/");
hostname = "http://" + hostname + "/";
} catch (Exception e) {
e.printStackTrace();
System.out.println("WebServer can not start");
}
}
public static void main(String[] args) {
try {
String hub = "http://pubsubhubbub.appspot.com/subscribe";
String hub_topic = "http://receivetemplate.eu01.aws.af.cm/feed/";
startServer();
int statusCode = sbcbr.subscribe(hub, hub_topic, hostname, null, null);
if (statusCode == 204){
System.out.println("the status code of the subscription is 204: the request was verified and that the subscription is active");
} else if (statusCode == 202){
System.out.println("the status code of the subscription is 202: the subscription has yet to be verified (i.e., the hub is using asynchronous verification)");
} else{
System.out.println("the status code of the subscription is:" + statusCode);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
If I replace hub_topic with http://pubsubhubbub-subscriber.appspot.com/ and if I pass pubsubhubbub-subscriber.appspot.com to InetAddress.getByName(), the response I get is 204 and everything works.
Can you give me some informations on what I'm doing wrong? Is there any error in my feed?
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 months ago.
Improve this question
I started to create an application for posting vacancies in jobs.google. I can not find an open api in order to post these vacancies directly on jobs.google through it.
Tell me how to do it.
I found a sample ready-made application, but since I have not yet encountered this, I have difficulties with the implementation
I also can’t figure out what is the difference between jobs.google and career or Cloud Talent Solution
import com.google.api.services.jobs.v3.CloudTalentSolution;
import com.google.api.services.jobs.v3.model.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
public class BasicJobSample {
private static final String DEFAULT_PROJECT_ID = "projects/" + System.getenv("GOOGLE_CLOUD_PROJECT");
private static CloudTalentSolution talentSolutionClient = JobServiceQuickstart.getTalentSolutionClient();
public static Job generateJobWithRequiredFields(String companyName) {
String requisitionId = "jobWithRequiredFields:" + String.valueOf(new Random().nextLong());
ApplicationInfo applicationInfo = new ApplicationInfo().setUris(Arrays.asList("http://careers.google.com"));
Job job = new Job().setRequisitionId(requisitionId).setTitle("Software Engineer")
.setCompanyName(companyName).setApplicationInfo(applicationInfo)
.setDescription("Design, develop, test, deploy, maintain and improve software.");
System.out.println("Job generated: " + job);
return job;
}
public static Job createJob(Job jobToBeCreated) throws IOException {
try {
CreateJobRequest createJobRequest = new CreateJobRequest().setJob(jobToBeCreated);
Job jobCreated = talentSolutionClient.projects().jobs().create(DEFAULT_PROJECT_ID, createJobRequest)
.execute();
System.out.println("Job created: " + jobCreated);
return jobCreated;
} catch (IOException e) {
System.out.println("Got exception while creating job");
throw e;
}
}
public static Job getJob(String jobName) throws IOException {
try {
Job jobExisted = talentSolutionClient.projects().jobs().get(jobName).execute();
System.out.println("Job existed: " + jobExisted);
return jobExisted;
} catch (IOException e) {
System.out.println("Got exception while getting job");
throw e;
}
}
public static Job updateJob(String jobName, Job jobToBeUpdated) throws IOException {
try {
UpdateJobRequest updateJobRequest = new UpdateJobRequest().setJob(jobToBeUpdated);
Job jobUpdated = talentSolutionClient.projects().jobs().patch(jobName, updateJobRequest).execute();
System.out.println("Job updated: " + jobUpdated);
return jobUpdated;
} catch (IOException e) {
System.out.println("Got exception while updating job");
throw e;
}
}
public static Job updateJobWithFieldMask(String jobName, String fieldMask, Job jobToBeUpdated)
throws IOException {
try {
UpdateJobRequest updateJobRequest = new UpdateJobRequest().setUpdateMask(fieldMask)
.setJob(jobToBeUpdated);
Job jobUpdated = talentSolutionClient.projects().jobs().patch(jobName, updateJobRequest).execute();
System.out.println("Job updated: " + jobUpdated);
return jobUpdated;
} catch (IOException e) {
System.out.println("Got exception while updating job");
throw e;
}
}
public static void deleteJob(String jobName) throws IOException {
try {
talentSolutionClient.projects().jobs().delete(jobName).execute();
System.out.println("Job deleted");
} catch (IOException e) {
System.out.println("Got exception while deleting job");
throw e;
}
}
public static void main(String... args) throws Exception {
Company companyToBeCreated = BasicCompanySample.generateCompany();
Company companyCreated = BasicCompanySample.createCompany(companyToBeCreated);
String companyName = companyCreated.getName();
Job jobToBeCreated = generateJobWithRequiredFields(companyName);
Job jobCreated = createJob(jobToBeCreated);
String jobName = jobCreated.getName();
getJob(jobName);
Job jobToBeUpdated = jobCreated.setDescription("changedDescription");
updateJob(jobName, jobToBeUpdated);
updateJobWithFieldMask(jobName, "title", new Job().setTitle("changedJobTitle"));
deleteJob(jobName);
BasicCompanySample.deleteCompany(companyName);
try {
ListCompaniesResponse listCompaniesResponse = talentSolutionClient.projects().companies()
.list(DEFAULT_PROJECT_ID).execute();
System.out.println("Request Id is " + listCompaniesResponse.getMetadata().getRequestId());
if (listCompaniesResponse.getCompanies() != null) {
for (Company company : listCompaniesResponse.getCompanies()) {
System.out.println(company.getName());
}
}
} catch (IOException e) {
System.out.println("Got exception while listing companies");
throw e;
}
}
}
import com.google.api.services.jobs.v3.CloudTalentSolution;
import com.google.api.services.jobs.v3.model.Company;
import com.google.api.services.jobs.v3.model.CreateCompanyRequest;
import com.google.api.services.jobs.v3.model.UpdateCompanyRequest;
import java.io.IOException;
import java.util.Random;
public class BasicCompanySample {
private static final String DEFAULT_PROJECT_ID = "projects/" + System.getenv("GOOGLE_CLOUD_PROJECT");
private static CloudTalentSolution talentSolutionClient = JobServiceQuickstart.getTalentSolutionClient();
public static Company generateCompany() {
String companyName = "company:" + String.valueOf(new Random().nextLong());
Company company = new Company().setDisplayName("Google")
.setHeadquartersAddress("1600 Amphitheatre Parkway Mountain View, CA 94043")
.setExternalId(companyName);
System.out.println("Company generated: " + company);
return company;
}
public static Company createCompany(Company companyToBeCreated) throws IOException {
try {
CreateCompanyRequest createCompanyRequest = new CreateCompanyRequest().setCompany(companyToBeCreated);
Company companyCreated = talentSolutionClient.projects().companies()
.create(DEFAULT_PROJECT_ID, createCompanyRequest).execute();
System.out.println("Company created: " + companyCreated);
return companyCreated;
} catch (IOException e) {
System.out.println("Got exception while creating company");
throw e;
}
}
public static Company getCompany(String companyName) throws IOException {
try {
Company companyExisted = talentSolutionClient.projects().companies().get(companyName).execute();
System.out.println("Company existed: " + companyExisted);
return companyExisted;
} catch (IOException e) {
System.out.println("Got exception while getting company");
throw e;
}
}
public static Company updateCompany(String companyName, Company companyToBeUpdated) throws IOException {
try {
UpdateCompanyRequest updateCompanyRequest = new UpdateCompanyRequest().setCompany(companyToBeUpdated);
Company companyUpdated = talentSolutionClient.projects().companies()
.patch(companyName, updateCompanyRequest).execute();
System.out.println("Company updated: " + companyUpdated);
return companyUpdated;
} catch (IOException e) {
System.out.println("Got exception while updating company");
throw e;
}
}
public static Company updateCompanyWithFieldMask(String companyName, String fieldMask,
Company companyToBeUpdated) throws IOException {
try {
// String foo = String.format("?updateCompanyFields=%s",fieldMask);
UpdateCompanyRequest updateCompanyRequest = new UpdateCompanyRequest().setUpdateMask(fieldMask)
.setCompany(companyToBeUpdated);
Company companyUpdated = talentSolutionClient.projects().companies()
.patch(companyName, updateCompanyRequest).execute();
System.out.println("Company updated: " + companyUpdated);
return companyUpdated;
} catch (IOException e) {
System.out.println("Got exception while updating company");
throw e;
}
}
public static void deleteCompany(String companyName) throws IOException {
try {
talentSolutionClient.projects().companies().delete(companyName).execute();
System.out.println("Company deleted");
} catch (IOException e) {
System.out.println("Got exception while deleting company");
throw e;
}
}
}
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.jobs.v3.CloudTalentSolution;
import com.google.api.services.jobs.v3.model.Company;
import com.google.api.services.jobs.v3.model.ListCompaniesResponse;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Collections;
public class JobServiceQuickstart {
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
private static final NetHttpTransport NET_HTTP_TRANSPORT = new NetHttpTransport();
private static final String SCOPES = "https://www.googleapis.com/auth/jobs";
private static final String DEFAULT_PROJECT_ID = "projects/" + System.getenv("GOOGLE_CLOUD_PROJECT");
private static final CloudTalentSolution talentSolutionClient = createTalentSolutionClient(generateCredential());
private static CloudTalentSolution createTalentSolutionClient(GoogleCredentials credential) {
String url = "https://jobs.googleapis.com";
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credential);
return new CloudTalentSolution.Builder(NET_HTTP_TRANSPORT, JSON_FACTORY, setHttpTimeout(requestInitializer))
.setApplicationName("JobServiceClientSamples").setRootUrl(url).build();
}
private static GoogleCredentials generateCredential() {
try {
// Credentials could be downloaded after creating service account
// set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable, for example:
// export GOOGLE_APPLICATION_CREDENTIALS=/path/to/your/key.json
return GoogleCredentials.getApplicationDefault().createScoped(Collections.singleton(SCOPES));
} catch (Exception e) {
System.out.print("Error in generating credential");
throw new RuntimeException(e);
}
}
private static HttpRequestInitializer setHttpTimeout(final HttpRequestInitializer requestInitializer) {
return request -> {
requestInitializer.initialize(request);
request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes"));
request.setConnectTimeout(1 * 60000); // 1 minute connect timeout
request.setReadTimeout(1 * 60000); // 1 minute read timeout
};
}
public static CloudTalentSolution getTalentSolutionClient() {
return talentSolutionClient;
}
I have added the code to my question. However, it throws an error, most likely this is due to authorization
Error in generating credentialException in thread "main" java.lang.ExceptionInInitializerError
at io.fortylines.tapintech.jobapi.BasicJobSample.<clinit>(BasicJobSample.java:13)
Caused by: java.lang.RuntimeException: java.io.IOException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
at io.fortylines.tapintech.jobapi.JobServiceQuickstart.generateCredential(JobServiceQuickstart.java:39)
at io.fortylines.tapintech.jobapi.JobServiceQuickstart.<clinit>(JobServiceQuickstart.java:22)
... 1 more
Caused by: java.io.IOException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
at com.google.auth.oauth2.DefaultCredentialsProvider.getDefaultCredentials(DefaultCredentialsProvider.java:134)
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:125)
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:97)
at io.fortylines.tapintech.jobapi.JobServiceQuickstart.generateCredential(JobServiceQuickstart.java:36)
... 2 more
#Configuration
public class Project1Config {
// Lists all service accounts for the current project.
public static void listServiceAccounts(String projectId) {
// String projectId = "my-project-id"
Iam service = null;
try {
service = initService();
} catch (IOException | GeneralSecurityException e) {
System.out.println("Unable to initialize service: \n" + e.toString());
return;
}
try {
ListServiceAccountsResponse response =
service.projects().serviceAccounts().list("projects/" + projectId).execute();
List<ServiceAccount> serviceAccounts = response.getAccounts();
for (ServiceAccount account : serviceAccounts) {
System.out.println("Name: " + account.getName());
System.out.println("Display Name: " + account.getDisplayName());
System.out.println("Email: " + account.getEmail());
System.out.println();
}
} catch (IOException e) {
System.out.println("Unable to list service accounts: \n" + e.toString());
}
}
private static Iam initService() throws GeneralSecurityException, IOException {
// Use the Application Default Credentials strategy for authentication. For more info, see:
// https://cloud.google.com/docs/authentication/production#finding_credentials_automatically
GoogleCredentials credential =
GoogleCredentials.getApplicationDefault()
.createScoped(Collections.singleton(IamScopes.CLOUD_PLATFORM));
// Initialize the IAM service, which can be used to send requests to the IAM API.
Iam service =
new Iam.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JacksonFactory.getDefaultInstance(),
new HttpCredentialsAdapter(credential))
.setApplicationName("service-accounts")
.build();
return service;
}
}
I also created a configuration class, but I still need to configure it.
When registering in the cloud, I registered the name of the project, and also received an email and a 21-digit number. How can I mark them in my project, since the error comes out the same
The Application Default Credentials are not available.
You have not configured the GOOGLE_APPLICATION_CREDENTIALS environment variable
This env var must point to the location of your credentials file.
How Application Default Credentials works
The domain name registrar Namecheap offers a service where customers can point their domains to their IP addresses simply using the browser.
How do I use a browser to dynamically update the host's IP?
The Dynamic DNS feature is available only for the domains pointed to our BasicDNS, PremiumDNS or FreeDNS.
Please substitute these with appropriate values for host, domain, password and IP:
https://dynamicdns.park-your-domain.com/update?host=[host]&domain=[domain_name]&password=[ddns_password]&ip=[your_ip]
Fields that are to be changed in the URL are: [host], [domain_name], [ddns_password] and [your_ip].
Nice feature, but I want to automate it. I came up with this in Java, but I'm not particularly familiar with HTTP protocols in the language and I'm not great at error handling. This won't get me a letter grade above a D any time soon but here's the general plan:
package myServerUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class IPPointer {
public static String IPinitial, Password;
// Time to wait between checks - decreases as IP changes more frequently, increases as IP changes less frequently
public static long delay = 21600000;
public static void main(String[] args) {
if (args.length == 3 & correctAddrFormat(args[0]) & correctNameFormat(args[1])) {
Thread dynamicdns = new Thread(new pointerDaemon(args [0], args[1], args[2]) );
dynamicdns.start();
}else {
System.out.println("Incorrect format - please enter as <IP address> <domain name> <DynamicDNS password>"
+ "\nExiting...");
}
}
// Should return true for argument in ip format, i.e., 198.0.0.1 splits to length 4
static boolean correctAddrFormat(String s) {
String[] parts = s.split(".");
if (parts.length == 4)
return true;
else
return false;
}
// Should return true for argument in domain name format, i.e., example.com splits to length 2
static boolean correctNameFormat(String s) {
String[] parts = s.split(".");
if (parts.length == 2)
return true;
else
return false;
}
}
class pointerDaemon implements Runnable{
private String currentIP, domain, password, fetchedIP;
public pointerDaemon(String ip, String domain, String password) {
this.currentIP = ip;
this.domain = domain;
this.password = password;
}
public void run() {
while(true) {
System.out.println("Attempting to synchronize IP pointer...");
fetchedIP = getIP();
if (fetchedIP.equals(currentIP)){
System.out.println("IP already synchronized.");
if (IPPointer.delay < 259200000L) {
IPPointer.delay = Math.round(IPPointer.delay * 1.1);
}
}else if(!fetchedIP.equals(currentIP) & !fetchedIP.equals(null)) {
currentIP = fetchedIP;
connectToDNS(currentIP, domain, password);
if (IPPointer.delay > 7200000) {
IPPointer.delay = Math.round(IPPointer.delay * 0.9);
}
}else if(fetchedIP.equals(null)) {
System.out.println("Bad public IP fetch...");
}else {
System.out.println("Don't know what's happening here. Don't much like it...");
}
try {
Thread.sleep(IPPointer.delay);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("Thread has died of insomnia...?");
break;
}
}
}
public void connectToDNS(String i, String d, String p) {
try {
URL updateService = new URL ("https://dynamicdns.park-your-domain.com/update?host=#&domain="+d+"&password="+p+"&ip="+i);
try {
URLConnection updateServiceConnection = updateService.openConnection();
updateServiceConnection.connect();
System.out.println("Update successful.");
} catch (IOException e) {
System.out.println("IOException in method connectToDNS...\nReturning without update...");
return;
}
} catch (MalformedURLException e) {
System.out.println("Malformed URL Exception in method connectToDNS...\nReturning without update...");
return;
}
}
public String getIP () {
try {
URL whois = new URL("http://bot.whatismyipaddress.com");
BufferedReader fetcher =
new BufferedReader(new InputStreamReader(whois.openStream()));
String s = fetcher.readLine().trim();
fetcher.close();
return s;
} catch (MalformedURLException e) {
System.out.println("Malformed URL Exception in method getIP...\nReturning null...");
} catch (IOException e) {
System.out.println("IOException in method getIP...\nReturning null...");
}
return null;
}
}
Theoretically, this works as is (assuming I didn't forget to escape all the proper special characters and that the URLConnection.connect() method is sufficient to send the request to update), but it's about as fault tolerant as an overripe tomato and developing robust code in Java is not my strong suit. Especially when it comes to networking...
I'd greatly appreciate some suggestions on how to clean this up and ensure reliability — thank you all.
I took the example from here http://www.rabbitmq.com/tutorials/tutorial-six-java.html, added one more RPC call from RPCClient and added some logging into stdout. As a result, when the second call is executed, rabbitmq uses the consumer with wrong correlation id which is not expected behavior. Is it a bug or am I getting anything wrong?
RPCServer:
package com.foo.rabbitmq;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class RPCServer {
private static final String RPC_QUEUE_NAME = "sap-consume";
private static int fib(int n) {
if (n ==0) return 0;
if (n == 1) return 1;
return fib(n-1) + fib(n-2);
}
public static void main(String[] argv) {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = null;
try {
connection = factory.newConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
channel.basicQos(1);
System.out.println(" [x] Awaiting RPC requests");
Consumer consumer = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
AMQP.BasicProperties replyProps = new AMQP.BasicProperties
.Builder()
.correlationId(properties.getCorrelationId())
.build();
String response = "";
try {
String message = new String(body,"UTF-8");
int n = Integer.parseInt(message);
System.out.println(" [.] fib(" + message + ")");
response += fib(n);
}
catch (RuntimeException e){
System.out.println(" [.] " + e.toString());
}
finally {
channel.basicPublish( "", properties.getReplyTo(), replyProps, response.getBytes("UTF-8"));
channel.basicAck(envelope.getDeliveryTag(), false);
// RabbitMq consumer worker thread notifies the RPC server owner thread
synchronized(this) {
this.notify();
}
}
}
};
channel.basicConsume(RPC_QUEUE_NAME, false, consumer);
// Wait and be prepared to consume the message from RPC client.
while (true) {
synchronized(consumer) {
try {
consumer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (IOException | TimeoutException e) {
e.printStackTrace();
}
finally {
if (connection != null)
try {
connection.close();
} catch (IOException _ignore) {}
}
}
}
RPCCLient:
package com.bar.rabbitmq;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;
public class RPCClient {
private Connection connection;
private Channel channel;
private String requestQueueName = "sap-consume";
private String replyQueueName;
public RPCClient() throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
connection = factory.newConnection();
channel = connection.createChannel();
replyQueueName = channel.queueDeclare().getQueue();
}
public String call(String message) throws IOException, InterruptedException {
final String corrId = UUID.randomUUID().toString();
AMQP.BasicProperties props = new AMQP.BasicProperties
.Builder()
.correlationId(corrId)
.replyTo(replyQueueName)
.build();
channel.basicPublish("", requestQueueName, props, message.getBytes("UTF-8"));
final BlockingQueue<String> response = new ArrayBlockingQueue<String>(1);
channel.basicConsume(replyQueueName, true, new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
if (properties.getCorrelationId().equals(corrId)) {
System.out.println("Correlation Id" + properties.getCorrelationId() + " corresponds to expected one.");
response.offer(new String(body, "UTF-8"));
} else {
System.out.println("Correlation Id" + properties.getCorrelationId() + " doesn't correspond to expected one " + corrId);
}
}
});
return response.take();
}
public void close() throws IOException {
connection.close();
}
public static void main(String[] argv) {
RPCClient rpc = null;
String response = null;
try {
rpc = new RPCClient();
System.out.println(" [x] Requesting fib(30)");
response = rpc.call("30");
System.out.println(" [.] Got '" + response + "'");
System.out.println(" [x] Requesting fib(40)");
response = rpc.call("40");
System.out.println(" [.] Got '" + response + "'");
} catch (IOException | TimeoutException | InterruptedException e) {
e.printStackTrace();
} finally {
if (rpc != null) {
try {
rpc.close();
} catch (IOException _ignore) {
}
}
}
}
}
Yes you found a bug in the tutorial code. I have opened a pull request to fix it here and you can find the explanation of what's happening as well:
https://github.com/rabbitmq/rabbitmq-tutorials/pull/174
NOTE: the RabbitMQ team monitors the rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.
This example is simplistic: it uses one queue for the reply. By sending a second request, you register a new consumer to the reply, but the consumer of the first request is still listening and actually steals the response of the second request. That's why the client seems to use the same correlation ID.
We updated the client code to use an exclusive, auto-delete queue for each request. This queue will be auto-deleted by the server because its only consumer is unsubscribed after the response has been received. This is a bit more involved but closer to a real-world scenario.
Note the best way to deal with the reply queue with RabbitMQ is to use direct reply-to. This uses pseudo-queues which are lighter than real queues. We don't mention direct reply-to in the tutorial to keep it as simple as possible, but this is the preferred feature to use in production.
I am trying to run the below code I am getting EOFException. The below is my output
Connected to ssl://REMOVED.messaging.internetofthings.ibmcloud.com:8883
.deliveryComplete() entered
Data published on topic iot-2/type/loradevice/id/cdef1234/cmd/cid/fmt/json and the msg is{"count":0,"cmd":"reset","time":"2017-01-25 18:38:34"}
connection true
Connection lost (32109) - java.io.EOFException
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:267)
at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65)
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107)
... 1 more
The code is below
package com.ibm.bluemixmqtt;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.json.JSONException;
import org.apache.commons.json.JSONObject;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
public class AppTest2
{
private MqttHandler1 handler;
/**
* #param args
*/
public static void main(String[] args)
{
new AppTest2().doApp();
}
/**
* Run the app
*/
public void doApp()
{
// Read properties from the conf file
Properties props = MqttUtil.readProperties("Mydata\\app.conf");
String org = "REMOVED";
String id = "REMOVED";
String authmethod = "REMOVED";
String authtoken = "REMOVED";
// isSSL property
String sslStr = props.getProperty("isSSL");
boolean isSSL = false;
if (sslStr.equals("T")) {
isSSL = true;
}
System.out.println("org: " + org);
System.out.println("id: " + id);
System.out.println("authmethod: " + authmethod);
System.out.println("authtoken" + authtoken);
System.out.println("isSSL: " + isSSL);
// Format: a:<orgid>:<app-id>
String clientId = "a:" + org + ":" + id;
String serverHost = org + MqttUtil.SERVER_SUFFIX;
handler = new MqttHandler1();
handler.connect(serverHost, clientId, authmethod, authtoken, isSSL);
publish();
}
public void publish(){
JSONObject jsonObj = new JSONObject();
String deviceid = "cdef1234";
try {
jsonObj.put("cmd", "reset");
jsonObj.put("count", 0);
jsonObj.put("time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
} catch (JSONException e) {
e.printStackTrace();
}
handler.publish(
"iot-2/type/" + MqttUtil.DEFAULT_DEVICE_TYPE + "/id/" + deviceid + "/cmd/" + MqttUtil.DEFAULT_CMD_ID + "/fmt/json",
jsonObj.toString(), false, 0);
}
}
class MqttHandler1 implements MqttCallback
{
private final static String DEFAULT_TCP_PORT = "1883";
private final static String DEFAULT_SSL_PORT = "8883";
private MqttClient client = null;
public MqttHandler1()
{
}
#Override
public void connectionLost(Throwable throwable)
{
if (throwable != null) {
System.out.println("Error3");
throwable.printStackTrace();
}
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken)
{
System.out.println(".deliveryComplete() entered");
}
#Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception
{
String payload = new String(mqttMessage.getPayload());
System.out.println(".messageArrived - Message received on topic " + topic + ": message is " + payload);
}
public void connect(String serverHost, String clientId, String authmethod, String authtoken, boolean isSSL)
{
// check if client is already connected
if (!isMqttConnected()) {
String connectionUri = null;
// tcp://<org-id>.messaging.internetofthings.ibmcloud.com:1883
// ssl://<org-id>.messaging.internetofthings.ibmcloud.com:8883
if (isSSL) {
connectionUri = "ssl://" + serverHost + ":" + DEFAULT_SSL_PORT;
} else {
connectionUri = "tcp://" + serverHost + ":" + DEFAULT_TCP_PORT;
}
if (client != null) {
try {
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
client = null;
}
try {
client = new MqttClient(connectionUri, clientId);
} catch (MqttException e) {
e.printStackTrace();
}
client.setCallback(this);
// create MqttConnectOptions and set the clean session flag
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setUserName(authmethod);
options.setPassword(authtoken.toCharArray());
options.setKeepAliveInterval(2000);
// If SSL is used, do not forget to use TLSv1.2
if (isSSL) {
java.util.Properties sslClientProps = new java.util.Properties();
sslClientProps.setProperty("com.ibm.ssl.protocol", "TLSv1.2");
options.setSSLProperties(sslClientProps);
}
try {
// connect
client.connect(options);
System.out.println("Connected to " + connectionUri);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
public void disconnect()
{
// check if client is actually connected
if (isMqttConnected()) {
try {
// disconnect
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
}
public void subscribe(String topic, int qos)
{
// check if client is connected
if (isMqttConnected()) {
try {
client.subscribe(topic, qos);
System.out.println("Subscribed: " + topic);
} catch (MqttException e) {
e.printStackTrace();
}
} else {
connectionLost(null);
}
}
public void unsubscribe(String topic)
{
// check if client is connected
if (isMqttConnected()) {
try {
client.unsubscribe(topic);
} catch (MqttException e) {
e.printStackTrace();
}
} else {
connectionLost(null);
}
}
public void publish(String topic, String message, boolean retained, int qos)
{
// check if client is connected
if (isMqttConnected()) {
// create a new MqttMessage from the message string
MqttMessage mqttMsg = new MqttMessage(message.getBytes());
// set retained flag
mqttMsg.setRetained(retained);
// set quality of service
mqttMsg.setQos(qos);
try {
client.publish(topic, mqttMsg);
System.out.println("Data published on topic " + topic + " and the msg is" + mqttMsg);
System.out.println("connection "+client.isConnected());
} catch (MqttPersistenceException e) {
System.out.println("Error1");
e.printStackTrace();
} catch (MqttException e) {
System.out.println("Error1");
e.printStackTrace();
}
} else {
connectionLost(null);
}
}
private boolean isMqttConnected()
{
boolean connected = false;
try {
if ((client != null) && (client.isConnected())) {
connected = true;
}
} catch (Exception e) {
// swallowing the exception as it means the client is not connected
}
return connected;
}
}
Any one help me on this.
Thanks in adavance.
the EOFException might indicates that the clientID is reused and the access is blocked... make sure that you only call once the connect method... possibly use only the SSL or non-SSL connection sequence
As part of my lab this week I am suppose to convert a socket based chat application to RMI. So far I managed to connect server and client together and transfer data between them but the transfer is not continuous. What I mean is that when the client first connects t the server it broadcasts a message "X has entered the conversation" but that is all. Anything I type after that wont get broadcasted. I am about to pull out my hair. Please help.
public class ChatServer extends UnicastRemoteObject implements ChatMessage {
private static final long serialVersionUID = 1L;
private String sender;
private String message;
private ChatMessageType t;
public ChatServer() throws RemoteException {
super();
}
#Override
public void Message(String sender, ChatMessageType t, String message)
throws RemoteException {
this.sender = sender;
this.message = message;
this.t = t;
}
#Override
public String getSender() throws RemoteException {
return sender;
}
#Override
public String getMessage() throws RemoteException {
return message;
}
#Override
public ChatMessageType getType() throws RemoteException {
return t;
}
public String ToString() throws RemoteException{
String strMessage;
switch (t) {
case SETUP:
strMessage = sender + " has entered the conversation.";
break;
case TEARDOWN:
strMessage = sender + " has left the conversation.";
break;
case MESSAGE:
strMessage = sender + ": " + message;
break;
default:
strMessage = "";
}
return strMessage;
}
// driver.
public static void main(String arg[]) {
try {
ChatServer c = new ChatServer();
Registry registry = LocateRegistry.createRegistry(1099);
registry.rebind("Server", c);
System.out.println("Server bound in registry");
} catch (Exception e) {
System.out.println("Server error: " + e.getMessage());
e.printStackTrace();
}
}
}
public class ChatClient implements ActionListener {
// static private Socket c;
static ChatMessage obj = null;
// static private ObjectInputStream in;
// static private ObjectOutputStream out;
static private String name;
static private String host;
static private Integer port;
/**
* Launches this application
*/
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (args.length != 3) {
System.out
.println("Client requires exactly three args to run.");
System.exit(-1);
}
name = args[0];
host = args[1];
port = new Integer(args[2]);
final ChatClient application = new ChatClient();
application.getJFrame().setVisible(true);
try {
System.out.println("client: connecting to server...");
// c = new Socket(host, port);
obj = (ChatMessage) Naming.lookup("//" + host + ":" + port
+ "/Server");
System.out.println("client: connected!");
} catch (Exception e) {
System.out.println("client: " + e.getMessage());
System.exit(-1);
}
try {
// out = new ObjectOutputStream(c.getOutputStream());
// in = new ObjectInputStream(c.getInputStream());
// announce to other clients that you're here
// out.writeObject(new ChatMessage(name,
// ChatMessageType.SETUP, ""));
obj.Message(name, ChatMessageType.SETUP, "");
} catch (Exception e) {
}
// set up the client's listener as an anonymous thread that's
// always running
// new Thread(new Runnable(){
// public void run()
// {
// while(true)
// {
try {
System.out.println(name + ": waiting for data");
ChatMessage m = (ChatMessage) Naming.lookup("//" + host
+ ":" + port + "/Server");
System.out.println(name + ": data received");
application.updateTextArea(m.ToString());
} catch (Exception e) {
}
// }
// }
// }).start();
}
});
}
public void updateTextArea(final String message) {
conversation.setText(conversation.getText() + message + "\n");
// this will guarantee that the bottom of the conversation is visible.
conversation.setCaretPosition(conversation.getText().length());
}
// send button has been pressed, send the message to the server.
public void actionPerformed(ActionEvent e) {
if (send.getText().equals("Send")) {
try {
System.out.println(name + ": sending data");
// ChatMessage m = new ChatMessage(name,
// ChatMessageType.MESSAGE, message.getText());
// out.writeObject(m);
obj.Message(name, ChatMessageType.MESSAGE, message.getText());
message.setText(""); // clear the text box.
System.out.println(name + ": data sent");
} catch (Exception ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
}
}
enum ChatMessageType{
SETUP,
MESSAGE,
TEARDOWN
}public interface ChatMessage extends Remote{
public String getSender() throws RemoteException;
public String getMessage() throws RemoteException;
public ChatMessageType getType() throws RemoteException;
public void Message(String sender, ChatMessageType t, String message) throws RemoteException;
public String ToString() throws RemoteException;
I realize this question is pretty old and you probably figured out an answer for this, but, I thought I'd share an approach I took for going from Java sockets to RMI. Maybe it is useful for others looking to do the same thing.
I basically abstracted out the socket portion into a "Tunnel" object that represents a communication path between hosts. And the tunnel consists of several "channels", that represent a one-way communication between the source and destination.
You can check out more details at my blog here: http://www.thecodespot.com/?p=1