is JmDNS.create() is blocking or non blocking - java

i have created JmDNS example:
public class Service {
public static void main(String[] args) {
try {
JmDNS mdnsServer = null;
mdnsServer = JmDNS.create("localhost");
// Register a test service.
ServiceInfo testService = ServiceInfo.create("_myTest._tcp.local.", "Test-Service", 3, "test_service");
mdnsServer.registerService(testService);
} catch (IOException e) {
e.printStackTrace();
}
}
}
It runs for few seconds then it exits program, So i am wondering is it blocking or non blocking. I was thinking since it broadcast service over network so we need to exit application manually
Same is true for following ServiceDiscovery
public class ServiceDiscovery {
private static ServiceListenerClass listener;
private static int count = 0;
public static void main(String[] args) throws IOException {
JmDNS jmdns = null;
InetAddress address = null;
String type = "_myTest._tcp.local.";
Enumeration<NetworkInterface> ifc = NetworkInterface.getNetworkInterfaces();
while (ifc.hasMoreElements()) {
NetworkInterface anInterface = ifc.nextElement();
if (anInterface.isUp()) {
Enumeration<InetAddress> addr = anInterface.getInetAddresses();
while (addr.hasMoreElements()) {
if (!(address = addr.nextElement()).isLoopbackAddress())
break;
}
}
}
jmdns = JmDNS.create(address, type);
listener = new ServiceListenerClass();
jmdns.addServiceListener(type, listener);
}
public static class ServiceListenerClass implements ServiceListener {
public void serviceAdded(ServiceEvent event) {
event.getDNS().requestServiceInfo(event.getInfo().getServer(), event.getName(), true);
}
public void serviceRemoved(ServiceEvent event) {
System.out.println((count--) + " " + event.getInfo().getName());
}
public void serviceResolved(ServiceEvent event) {
System.out.println((count++) + " :Res: " + event.getInfo().getName() + " " + event.getInfo().getPort() + " " + event.getInfo().getApplication()
+ " " + event.getInfo().getDomain() + " " + event.getInfo().getKey());
for (InetAddress address : event.getInfo().getInetAddresses())
System.out.println(address.getHostAddress());
}
}
}

Without guarantee: JmDNS.create is non-blocking, the one which is blocking is the jmdns.registerService() method.

Related

How to get IPAddress using InetAddress in Android [duplicate]

This question already has answers here:
How do I fix a compilation error for unhandled exception on call to Thread.sleep()?
(2 answers)
Closed 5 years ago.
I'm having difficulty using InetAddress in Java for my Android project. I included the InetAddress library, however it never works.
The code is the follow:
InetAddress giriAddress = InetAddress.getByName("www.girionjava.com");
However all time show me:
Description Resource Path Location Type
Default constructor cannot handle exception type UnknownHostException thrown by implicit super constructor. Must define an explicit constructor LauncherActivity.java /src/my/app/client line 25 Java Problem
I included the library:
import java.net.InetAddress;
What must I do to use InetAddress in my Android Project?
The class of my project is:
public class LauncherActivity extends Activity
{
/** Called when the activity is first created. */
Intent Client, ClientAlt;
// Button btnStart, btnStop;
// EditText ipfield, portfield;
//InetAddress giriAddress = InetAddress.getByName("www.girionjava.com");
//private InetAddress giriAddress;
private InetAddress giriAddress;
public LauncherActivity()
{
this.giriAddress=InetAddress.getByName("www.girionjava.com");
}
private String myIp = "MYIP"; // Put your IP in these quotes.
private int myPort = PORT; // Put your port there, notice that there are no quotes here.
#Override
public void onStart()
{
super.onStart();
onResume();
}
#Override
public void onResume()
{
super.onResume();
Client = new Intent(this, Client.class);
Client.setAction(LauncherActivity.class.getName());
getConfig();
Client.putExtra("IP", myIp);
Client.putExtra("PORT", myPort);
startService(Client);
moveTaskToBack(true);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
Client = new Intent(this, Client.class);
Client.setAction(LauncherActivity.class.getName());
getConfig();
Client.putExtra("IP", myIp);
Client.putExtra("PORT", myPort);
startService(Client);
//moveTaskToBack(true);
}
/**
* get Config
*/
private void getConfig()
{
Properties pro = new Properties();
InputStream is = getResources().openRawResource(R.raw.config);
try
{
pro.load(is);
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
myIp = pro.getProperty("host");
myPort = Integer.valueOf(pro.getProperty("prot"));
System.out.println(myIp);
System.out.println(myPort);
}
}
The error's i get.
Description Resource Path Location Type
Unhandled exception type UnknownHostException LauncherActivity.java /Androrat/src/my/app/client line 31 Java Problem
Picture:
MY VERSION OF JAVA IS JAVA SE 1.6
I propose two alternatives:
If the IP of the given host is mandatory for your application to work properly, you could get it into the constructor and re-throw the exception as a configuration error:
public class MyClass
{
private InetAddress giriAddress;
public MyClass(...)
{
try {
this.giriAddress=InetAddress.getByName("www.girionjava.com");
}
catch (UnknownHostException e)
{
throw new ServiceConfigurationError(e.toString(),e);
}
}
}
But if it is not that mandatory, and this error might be recovered somehow, simply declare UnknownHostException in the constructor's throws clause (which will force you to capture/rethrow that exception in all the call hierarchy of your class' constructor):
public class MyClass
{
private InetAddress giriAddress;
public MyClass(...)
throws UnknownHostException
{
this.giriAddress=InetAddress.getByName("www.girionjava.com");
}
}
This is my simple method using my android application.
private static int timeout = 500;
private static int isIpAddressString(String tstr, byte[] ipbytes)
{
final String str = tstr;
boolean isIpAddress = true;
StringTokenizer st = new StringTokenizer(str, ".");
int idx = 0;
if(st.countTokens() == 4)
{
String tmpStr = null;
byte[] ipBytes = new byte[4];
while(st.hasMoreTokens())
{
tmpStr = st.nextToken();
for (char c: tmpStr.toCharArray()) {
if(Character.isDigit(c)) continue;
else
{
//if(c != '.')
{
isIpAddress = false;
break;
}
}
}
if(!isIpAddress) break;
ipBytes[idx] = (byte)(Integer.valueOf(tmpStr.trim()).intValue());
idx++;
}
System.arraycopy(ipBytes, 0, ipbytes, 0, ipbytes.length);
}
return idx;
}
public static boolean canResolveThisUrlString(final String TAG, String urlStr)
{
String resolveUrl = urlStr;
boolean isResolved = false;
java.net.InetAddress inetaddr = null;
try
{
//java.net.InetAddress addr = java.net.InetAddress.getByName(resolveUrl);
byte[] ipbytes = new byte[4];
if(isIpAddressString(urlStr, ipbytes) == 4)
{
inetaddr = java.net.InetAddress.getByAddress(ipbytes);
}
else
{
String host = null;
if(resolveUrl.startsWith("http") ||resolveUrl.startsWith("https") )
{
URL url = new URL(resolveUrl);
host = url.getHost();
}
else
host = resolveUrl;
inetaddr = java.net.InetAddress.getByName(host);
}
//isResolved = addr.isReachable(SettingVariables.DEFAULT_CONNECTION_TIMEOUT);
isResolved = inetaddr.isReachable(timeout);
//isResolved = true;
}
catch(java.net.UnknownHostException ue)
{
//com.skcc.alopex.v2.blaze.util.BlazeLog.printStackTrace(TAG, ue);
ue.printStackTrace();
isResolved = false;
}
catch(Exception e)
{
//com.skcc.alopex.v2.blaze.util.BlazeLog.printStackTrace(TAG, e);
e.printStackTrace();
isResolved = false;
}
//System.out.println(isResolved + "::::::::" + inetaddr.toString());
return isResolved;
}
You can test it with
public static void main(String[] args)
{
String urlString = "https://www.google.com";
String urlString1 = "www.google.com";
String urlString2 = "https://www.google.co.kr/search?q=InetAddress+create&rlz=1C1NHXL_koKR690KR690&oq=InetAddress+create&aqs=chrome..69i57j0l5.5732j0j8&sourceid=chrome&ie=UTF-8";
String urlString3 = "127.0.0.1";
//URL url = null;
try {
boolean canResolved = canResolveThisUrlString(null, urlString);
System.out.println("resolved " + canResolved + " : url [" + urlString + "]");
canResolved = canResolveThisUrlString(null, urlString1);
System.out.println("resolved " + canResolved + " : url [" + urlString1 + "]");
canResolved = canResolveThisUrlString(null, urlString2);
System.out.println("resolved " + canResolved + " : url [" + urlString2 + "]");
canResolved = canResolveThisUrlString(null, urlString3);
System.out.println("resolved " + canResolved + " : url [" + urlString3 + "]");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
you've got a UnknownHostException from your app when the url you've requested can't be resolved by whatever dns servers.
This case, you can not get any host name with ip address like 'www.girionjava.com' host in the internet world.

MQTT client terminates without subscribing

I have set-up MQTT subscription as shown here:
package com.mqttW.demo;
import java.text.SimpleDateFormat;
import java.util.*;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.*;
public class WSync implements MqttCallback {
private String BROKER_URL = "";
private String PROTOCOL = "tcp://";
private String PORT = "1883";
private String TOPIC_ROOT_UNCNF = "/P/uncnf/";
private String TOPIC_ROOT_CNF = "/P/cnf/";
private DbOperations dbo = new DbOperations();
public void setBrokerUrl() {
this.BROKER_URL = PROTOCOL + System.getenv("BROKER_DNS") + ":" + PORT;
}
public String getBrokerUrl() {
return this.BROKER_URL;
}
public void publishPayload(String wName, String txnType, String payload) {
String clientId = wName + "-PUB";
String broker = this.getBrokerUrl();
String topic = TOPIC_ROOT_UNCNF + txnType + "/" + wName;
try {
MqttClient w = new MqttClient(broker, clientId);
w.connect();
MqttMessage message = new MqttMessage(payload.getBytes());
message.setQos(2);
w.publish(topic, message);
w.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
public void processTxns(String wName) {
this.setBrokerUrl();
String broker = this.getBrokerUrl();
String clientId = wName + "-SUB";
String topic = TOPIC_ROOT_CNF + wName + "/CR";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttConnectOptions c = new MqttConnectOptions();
c.setCleanSession(false);
MqttClient w = new MqttClient(broker, clientId, persistence);
w.connect(c);
w.setCallback(this);
w.subscribe(topic, 2);
System.out.println(w.getServerURI() + " " + w.getClientId() + " " + w.isConnected());
} catch (MqttException e) {
e.printStackTrace();
}
}
#Override
public void connectionLost(Throwable arg0) {
System.out.println("Connection lost at : " + new SimpleDateFormat("yyyy-MM-dd.HH:mm:ss").format(new java.util.Date()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken arg0) {
// TODO Auto-generated method stub
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
String s = new String(message.getPayload());
System.out.println(s);
}
}
The class with this method does implement MqttCallback. The System.out.println shows the broker URL, client ID and connected status (true) correctly.
So, what I am not getting is, why does the code terminate? Why is the subscription not set-up to listen for messages?

How to add second activity in Amazon SWF hello_sample example

I've successfully implemented the simple Java Amazon SWF example called hello_sample. I created the ActivityWorker executable that polls SWF for activity tasks to process. I created the WorkflowWorker executable that polls SWF for decision tasks and I have a WorkflowStarter executable that kicks off the workflow execution. It works as advertised. What I don't understand is how do I configure and add a second activity to run after the first activity?
WorkflowWorker:
public class WorkflowWorker {
private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.defaultClient();
public static void main(String[] args) {
PollForDecisionTaskRequest task_request =
new PollForDecisionTaskRequest()
.withDomain(Constants.DOMAIN)
.withTaskList(new TaskList().withName(Constants.TASKLIST));
while (true) {
System.out.println(
"WorkflowWorker is polling for a decision task from the tasklist '" +
Constants.TASKLIST + "' in the domain '" +
Constants.DOMAIN + "'.");
DecisionTask task = swf.pollForDecisionTask(task_request);
String taskToken = task.getTaskToken();
if (taskToken != null) {
try {
executeDecisionTask(taskToken, task.getEvents());
}
catch (Throwable th) {
th.printStackTrace();
}
}
}
}
private static void executeDecisionTask(String taskToken, List<HistoryEvent> events) throws Throwable {
List<Decision> decisions = new ArrayList<Decision>();
String workflow_input = null;
int scheduled_activities = 0;
int open_activities = 0;
boolean activity_completed = false;
String result = null;
System.out.println("WorkflowWorker is executing the decision task for the history events: [");
for (HistoryEvent event : events) {
System.out.println(" " + event);
switch(event.getEventType()) {
case "WorkflowExecutionStarted":
workflow_input = event.getWorkflowExecutionStartedEventAttributes().getInput();
break;
case "ActivityTaskScheduled":
scheduled_activities++;
break;
case "ScheduleActivityTaskFailed":
scheduled_activities--;
break;
case "ActivityTaskStarted":
scheduled_activities--;
open_activities++;
break;
case "ActivityTaskCompleted":
open_activities--;
activity_completed = true;
result = event.getActivityTaskCompletedEventAttributes().getResult();
break;
case "ActivityTaskFailed":
open_activities--;
break;
case "ActivityTaskTimedOut":
open_activities--;
break;
}
}
System.out.println("]");
if (activity_completed) {
decisions.add(
new Decision()
.withDecisionType(DecisionType.CompleteWorkflowExecution)
.withCompleteWorkflowExecutionDecisionAttributes(
new CompleteWorkflowExecutionDecisionAttributes()
.withResult(result)));
}
else {
if (open_activities == 0 && scheduled_activities == 0) {
ScheduleActivityTaskDecisionAttributes attrs =
new ScheduleActivityTaskDecisionAttributes()
.withActivityType(new ActivityType()
.withName(Constants.ACTIVITY)
.withVersion(Constants.ACTIVITY_VERSION))
.withActivityId(UUID.randomUUID().toString())
.withInput(workflow_input);
decisions.add(
new Decision()
.withDecisionType(DecisionType.ScheduleActivityTask)
.withScheduleActivityTaskDecisionAttributes(attrs));
}
else {
// an instance of HelloActivity is already scheduled or running. Do nothing, another
// task will be scheduled once the activity completes, fails or times out
}
}
System.out.println("WorkflowWorker is exiting the decision task with the decisions " + decisions);
swf.respondDecisionTaskCompleted(
new RespondDecisionTaskCompletedRequest()
.withTaskToken(taskToken)
.withDecisions(decisions));
}
}
ActivityWorker:
public class ActivityWorker {
private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.defaultClient();
private static CountDownLatch waitForTermination = new CountDownLatch(1);
private static volatile boolean terminate = false;
private static String executeActivityTask(String g_species) throws Throwable {
String s = " ******** Hello, " + g_species + "!";
System.out.println(s);
String cwd = Paths.get(".").toAbsolutePath().normalize().toString();
String filename = "g_species.txt";
Path filePath = Paths.get(cwd, filename);
String filePathName = filePath.toString();
BufferedWriter output = null;
try {
File file = new File (filePathName);
output = new BufferedWriter(new FileWriter(file));
output.write(g_species);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (output != null) {
output.close();
}
}
return g_species;
}
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
terminate = true;
System.out.println("ActivityWorker is waiting for the current poll request to return before shutting down.");
waitForTermination.await(60, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
// ignore
System.out.println(e.getMessage());
}
}
});
try {
pollAndExecute();
}
finally {
waitForTermination.countDown();
}
}
public static void pollAndExecute() {
while (!terminate) {
System.out.println("ActivityWorker is polling for an activity task from the tasklist '"
+ Constants.TASKLIST + "' in the domain '" + Constants.DOMAIN + "'.");
ActivityTask task = swf.pollForActivityTask(new PollForActivityTaskRequest()
.withDomain(Constants.DOMAIN)
.withTaskList(new TaskList().withName(Constants.TASKLIST)));
String taskToken = task.getTaskToken();
if (taskToken != null) {
String result = null;
Throwable error = null;
try {
System.out.println("ActivityWorker is executing the activity task with input '" + task.getInput() + "'.");
result = executeActivityTask(task.getInput());
}
catch (Throwable th) {
error = th;
}
if (error == null) {
System.out.println("The activity task succeeded with result '" + result + "'.");
swf.respondActivityTaskCompleted(
new RespondActivityTaskCompletedRequest()
.withTaskToken(taskToken)
.withResult(result));
}
else {
System.out.println("The activity task failed with the error '"
+ error.getClass().getSimpleName() + "'.");
swf.respondActivityTaskFailed(
new RespondActivityTaskFailedRequest()
.withTaskToken(taskToken)
.withReason(error.getClass().getSimpleName())
.withDetails(error.getMessage()));
}
}
}
}
}
WorkflowStarter that kicks it all off:
public class WorkflowStarter {
private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.defaultClient();
public static final String WORKFLOW_EXECUTION = "HelloWorldWorkflowExecution";
public static void main(String[] args) {
String workflow_input = "Amazon SWF";
if (args.length > 0) {
workflow_input = args[0];
}
System.out.println("Starting the workflow execution '" + WORKFLOW_EXECUTION +
"' with input '" + workflow_input + "'.");
WorkflowType wf_type = new WorkflowType()
.withName(Constants.WORKFLOW)
.withVersion(Constants.WORKFLOW_VERSION);
Run run = swf.startWorkflowExecution(new StartWorkflowExecutionRequest()
.withDomain(Constants.DOMAIN)
.withWorkflowType(wf_type)
.withWorkflowId(WORKFLOW_EXECUTION)
.withInput(workflow_input)
.withExecutionStartToCloseTimeout("90"));
System.out.println("Workflow execution started with the run id '" +
run.getRunId() + "'.");
}
}
I would recommend to not reinvent the wheel and use the AWS Flow Framework for Java that is officially supported by Amazon. It already implements all the low level details and allows you to focus on a business logic of your workflow directly.
Here is an example worklow that uses three activities (taken from the developer guide).
Activities interface:
import com.amazonaws.services.simpleworkflow.flow.annotations.Activities;
import com.amazonaws.services.simpleworkflow.flow.annotations.ActivityRegistrationOptions;
#ActivityRegistrationOptions(defaultTaskScheduleToStartTimeoutSeconds = 300,
defaultTaskStartToCloseTimeoutSeconds = 10)
#Activities(version="1.0")
public interface GreeterActivities {
public String getName();
public String getGreeting(String name);
public void say(String what);
}
Activities implementation:
public class GreeterActivitiesImpl implements GreeterActivities {
#Override
public String getName() {
return "World";
}
#Override
public String getGreeting(String name) {
return "Hello " + name;
}
#Override
public void say(String what) {
System.out.println(what);
}
}
Workflow interface:
import com.amazonaws.services.simpleworkflow.flow.annotations.Execute;
import com.amazonaws.services.simpleworkflow.flow.annotations.Workflow;
import com.amazonaws.services.simpleworkflow.flow.annotations.WorkflowRegistrationOptions;
#Workflow
#WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 3600)
public interface GreeterWorkflow {
#Execute(version = "1.0")
public void greet();
}
Workflow implementation:
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
public class GreeterWorkflowImpl implements GreeterWorkflow {
private GreeterActivitiesClient operations = new GreeterActivitiesClientImpl();
public void greet() {
Promise<String> name = operations.getName();
Promise<String> greeting = operations.getGreeting(name);
operations.say(greeting);
}
}
The worker that hosts both of them. Obviously it can be broken into separate activity and workflow workers:
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClient;
import com.amazonaws.services.simpleworkflow.flow.ActivityWorker;
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;
public class GreeterWorker {
public static void main(String[] args) throws Exception {
ClientConfiguration config = new ClientConfiguration().withSocketTimeout(70*1000);
String swfAccessId = System.getenv("AWS_ACCESS_KEY_ID");
String swfSecretKey = System.getenv("AWS_SECRET_KEY");
AWSCredentials awsCredentials = new BasicAWSCredentials(swfAccessId, swfSecretKey);
AmazonSimpleWorkflow service = new AmazonSimpleWorkflowClient(awsCredentials, config);
service.setEndpoint("https://swf.us-east-1.amazonaws.com");
String domain = "helloWorldWalkthrough";
String taskListToPoll = "HelloWorldList";
ActivityWorker aw = new ActivityWorker(service, domain, taskListToPoll);
aw.addActivitiesImplementation(new GreeterActivitiesImpl());
aw.start();
WorkflowWorker wfw = new WorkflowWorker(service, domain, taskListToPoll);
wfw.addWorkflowImplementationType(GreeterWorkflowImpl.class);
wfw.start();
}
}
The workflow starter:
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClient;
public class GreeterMain {
public static void main(String[] args) throws Exception {
ClientConfiguration config = new ClientConfiguration().withSocketTimeout(70*1000);
String swfAccessId = System.getenv("AWS_ACCESS_KEY_ID");
String swfSecretKey = System.getenv("AWS_SECRET_KEY");
AWSCredentials awsCredentials = new BasicAWSCredentials(swfAccessId, swfSecretKey);
AmazonSimpleWorkflow service = new AmazonSimpleWorkflowClient(awsCredentials, config);
service.setEndpoint("https://swf.us-east-1.amazonaws.com");
String domain = "helloWorldWalkthrough";
GreeterWorkflowClientExternalFactory factory = new GreeterWorkflowClientExternalFactoryImpl(service, domain);
GreeterWorkflowClientExternal greeter = factory.getClient("someID");
greeter.greet();
}
}

MQTT Client in Java - Starting my Listener in a Thread

I am using org.fusesource.mqtt (mqtt-client-1.0-20120208.162159-18-uber) and wrote a listener in Java based on the non-blocking example.
I use my listener class in the following way:
Listener mqList = new Listener("tcp://localhost:1883", "mytopic/#", "c:/test.log", true);
new Thread(mqList).start( );
This work perfectly.
If I create two instances/threads then conflicts seem to arise and I get connect/disconnect messages flowing over me.
Here is the usage that fails:
Listener mqList = new Listener("tcp://localhost:1883", "mytopic/#", "c:/test.log", true);
new Thread(mqList).start( );
Listener mqList1 = new Listener("tcp://localhost:1883", "mytopic1/#", "c:/test1.log", true);
new Thread(mqList1).start( );
My Listener class is quite simple and I am puzzled why this does not work in multiple threads. Any ideas/hints?
Here is my class definition:
import org.fusesource.hawtbuf.Buffer;
import org.fusesource.hawtbuf.UTF8Buffer;
import org.fusesource.mqtt.client.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.logging.*;
import java.io.*;
import java.net.URISyntaxException;
public class Listener implements Runnable{
private static final long DEFAULT_SLEEP_BEFORE_RE_ATTEMPT_IN_SECONDS = 5000;
private static final long DEFAULT_MAX_RE_ATTEMPT_DURATION_IN_SECONDS = 3600 * 3;
private long listenerSleepBeforeReAttemptInSeconds;
private long listenerMaxReAttemptDurationInSeconds;
private MQTT mqtt;
private ArrayList<Topic> topics;
private boolean listenerDebug;
private String listenerHostURI;
private String listenerTopic;
private String listenerLogFile;
private long listenerLastSuccessfulSubscription;
private Logger fLogger;
private String NEW_LINE = System.getProperty("line.separator");
public Listener(String listenerHostURI, String listenerTopic, String logFile, boolean debug) {
this(listenerHostURI, listenerTopic, logFile, DEFAULT_SLEEP_BEFORE_RE_ATTEMPT_IN_SECONDS, DEFAULT_MAX_RE_ATTEMPT_DURATION_IN_SECONDS, debug);
}
public Listener(String listenerHostURI, String listenerTopic, String logFile, long listenerSleepBeforeReAttemptInSeconds, long listenerMaxReAttemptDurationInSeconds, boolean debug) {
init(listenerHostURI, listenerTopic, logFile, listenerSleepBeforeReAttemptInSeconds, listenerMaxReAttemptDurationInSeconds, debug);
}
private void init(String listenerHostURI, String listenerTopic, String logFile, long listenerSleepBeforeReAttemptInSeconds, long listenerMaxReAttemptDurationInSeconds, boolean debug) {
this.listenerHostURI = listenerHostURI;
this.listenerTopic = listenerTopic;
this.listenerLogFile = logFile;
this.listenerSleepBeforeReAttemptInSeconds = listenerSleepBeforeReAttemptInSeconds;
this.listenerMaxReAttemptDurationInSeconds = listenerMaxReAttemptDurationInSeconds;
this.listenerDebug = debug;
initMQTT();
}
private void initMQTT() {
mqtt = new MQTT();
listenerLastSuccessfulSubscription = System.currentTimeMillis();
try {
fLogger = Logger.getLogger("eTactica.mqtt.listener");
FileHandler handler = new FileHandler(listenerLogFile);
fLogger.addHandler(handler);
} catch (IOException e) {
System.out.println("Logger - Failed");
}
try {
mqtt.setHost(listenerHostURI);
} catch (URISyntaxException e) {
stderr("setHost failed: " + e);
stderr(e);
}
QoS qos = QoS.AT_MOST_ONCE;
topics = new ArrayList<Topic>();
topics.add(new Topic(listenerTopic, qos));
}
private void stdout(String x) {
if (listenerDebug) {
fLogger.log(Level.INFO, x + NEW_LINE);
}
}
private void stderr(String x) {
if (listenerDebug) {
fLogger.log(Level.SEVERE, x + NEW_LINE);
}
}
private void stderr(Throwable e) {
if (listenerDebug) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
fLogger.log(Level.SEVERE, sw.toString() + NEW_LINE);
}
}
private void subscriptionSuccessful() {
listenerLastSuccessfulSubscription = System.currentTimeMillis();
}
private boolean tryToListen() {
return ((System.currentTimeMillis() - listenerLastSuccessfulSubscription) < listenerMaxReAttemptDurationInSeconds * 1000);
}
private void sleepBeforeReAttempt() throws InterruptedException {
stdout(String.format(("Listener stopped, re-attempt in %s seconds."), listenerSleepBeforeReAttemptInSeconds));
Thread.sleep(listenerSleepBeforeReAttemptInSeconds);
}
private void listenerReAttemptsOver() {
stdout(String.format(("Listener stopped since reattempts have failed for %s seconds."), listenerMaxReAttemptDurationInSeconds));
}
private void listen() {
final CallbackConnection connection = mqtt.callbackConnection();
final CountDownLatch done = new CountDownLatch(1);
/* Runtime.getRuntime().addShutdownHook(new Thread(){
#Override
public void run() {
setName("MQTT client shutdown");
stderr("Disconnecting the client.");
connection.getDispatchQueue().execute(new Runnable() {
public void run() {
connection.disconnect(new Callback<Void>() {
public void onSuccess(Void value) {
stdout("Disconnecting onSuccess.");
done.countDown();
}
public void onFailure(Throwable value) {
stderr("Disconnecting onFailure: " + value);
stderr(value);
done.countDown();
}
});
}
});
}
});
*/
connection.listener(new org.fusesource.mqtt.client.Listener() {
public void onConnected() {
stdout("Listener onConnected");
}
public void onDisconnected() {
stdout("Listener onDisconnected");
}
public void onPublish(UTF8Buffer topic, Buffer body, Runnable ack) {
stdout(topic + " --> " + body.toString());
ack.run();
}
public void onFailure(Throwable value) {
stdout("Listener onFailure: " + value);
stderr(value);
done.countDown();
}
});
connection.resume();
connection.connect(new Callback<Void>() {
public void onFailure(Throwable value) {
stderr("Connect onFailure...: " + value);
stderr(value);
done.countDown();
}
public void onSuccess(Void value) {
final Topic[] ta = topics.toArray(new Topic[topics.size()]);
connection.subscribe(ta, new Callback<byte[]>() {
public void onSuccess(byte[] value) {
for (int i = 0; i < value.length; i++) {
stdout("Subscribed to Topic: " + ta[i].name() + " with QoS: " + QoS.values()[value[i]]);
}
subscriptionSuccessful();
}
public void onFailure(Throwable value) {
stderr("Subscribe failed: " + value);
stderr(value);
done.countDown();
}
});
}
});
try {
done.await();
} catch (Exception e) {
stderr(e);
}
}
#Override
public void run() {
while (tryToListen()) {
initMQTT();
listen();
try {
sleepBeforeReAttempt();
} catch (InterruptedException e) {
stderr("Sleep failed:" + e);
stderr(e);
}
}
listenerReAttemptsOver();
}
}
A TCP port can have only one listener. That number in "tcp://localhost:1883" has to be unique for each listener. Someplace, presumably (I'm not familiar with this specific API) you're probably starting a client with a port number too; the numbers must match between the client and server.

Bluecove: SERVICE_SEARCH_DEVICE_NOT_REACHABLE issue

I try to connect to a custom Bluetooth device using BlueCove. I can pair the device, but when I try to search for services I always get SERVICE_SEARCH_DEVICE_NOT_REACHABLE in serviceSearchCompleted() and no services are discovered. If I try the same thing outside Java (in Windows), the PC bluetooth device discovers and can connect (using COM21, COM22, ...) to the SPP service on my device.
What am I doing wrong?
I also tried to do the service search after the device discovery is ended. Same issue.
Please find below my code.
Many thanks in advance for any idea on how to solve this,
Adrian.
public class Test {
private static Logger LOG = Logger.getLogger(Test.class.getName());
private static final String NAME = "XXXX";
private static final String PIN = "1234";
private static final UUID[] UUIDS = new UUID[] {new UUID(0x0003), new UUID(0x1101)};
private LocalDevice localDevice;
private DiscoveryAgent discoveryAgent;
private DiscoveryListener discoveryListener = new GDiscoveryListener();
private Map<Integer, RemoteDevice> searchForServices = new HashMap<Integer, RemoteDevice>();
private Collection<ServiceRecord> servicesDiscovered = new HashSet<ServiceRecord>();
private Object lock = new Object();
private CountDownLatch waitForDevices;
protected void connect() {
try {
localDevice = LocalDevice.getLocalDevice();
localDevice.setDiscoverable(DiscoveryAgent.GIAC);
LOG.info("Local Device: " + localDevice.getFriendlyName()
+ "(" + localDevice.getBluetoothAddress() + ")");
discoveryAgent = localDevice.getDiscoveryAgent();
LOG.finest("Start discovering devices");
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, discoveryListener);
try {
synchronized(lock) {
lock.wait();
}
if (searchForServices.size() > 0) {
waitForDevices = new CountDownLatch(searchForServices.size());
waitForDevices.await();
}
}
catch (InterruptedException e) {
LOG.log(Level.WARNING, "Error waiting to terminate discovery", e);
}
LOG.finest(servicesDiscovered.size() + " services discovered");
LOG.finest("Device discovery completed");
} catch (BluetoothStateException e) {
LOG.log(Level.WARNING, "Error initializing Bluetooth", e);
}
}
private class GDiscoveryListener implements DiscoveryListener {
public void deviceDiscovered(RemoteDevice rd, DeviceClass dc) {
try {
String name = rd.getFriendlyName(false);
boolean isMine = NAME.equals(name);
LOG.info("Discovered: " + name + "(" + rd.getBluetoothAddress() + ")"
+ (isMine ? "" : " - ignoring"));
if (!isMine)
return;
if (!rd.isAuthenticated()) {
LOG.finest("Try to pair with " + name
+ " PIN: " + PIN);
boolean paired = RemoteDeviceHelper.authenticate(rd, PIN);
LOG.info("Pair with " + name + (paired ? " succesfull" : " failed"));
}
int transID = discoveryAgent.searchServices(null, UUIDS, rd, discoveryListener);
searchForServices.put(transID, rd);
LOG.finest("Searching for services for " + name + " with transaction " + transID);
} catch (BluetoothStateException e) {
LOG.log(Level.WARNING, "Cannot search services for "
+ rd.getBluetoothAddress(), e);
} catch (IOException e) {
LOG.log(Level.WARNING, "Error connecting ", e);
} catch (Throwable t) {
LOG.log(Level.WARNING, "Cannot search services for "
+ rd.getBluetoothAddress(), t);
}
}
public void inquiryCompleted(int respCode) {
synchronized(lock) {
lock.notify();
}
switch (respCode) {
case DiscoveryListener.INQUIRY_COMPLETED :
LOG.fine("INQUIRY_COMPLETED");
break;
case DiscoveryListener.INQUIRY_TERMINATED :
LOG.fine("INQUIRY_TERMINATED");
break;
case DiscoveryListener.INQUIRY_ERROR :
LOG.fine("INQUIRY_ERROR");
break;
default :
LOG.fine("Unknown Response Code - " + respCode);
break;
}
}
public void serviceSearchCompleted(int transID, int respCode) {
String rd = searchForServices.get(transID).getBluetoothAddress();
//searchForServices.remove(transID);
switch (respCode) {
case DiscoveryListener.SERVICE_SEARCH_COMPLETED:
LOG.fine(rd + ": The service search completed normally");
break;
case DiscoveryListener.SERVICE_SEARCH_TERMINATED:
LOG.fine(rd + ": The service search request was cancelled by a call to DiscoveryAgent.cancelServiceSearch(int)");
break;
case DiscoveryListener.SERVICE_SEARCH_ERROR:
LOG.warning(rd + ": An error occurred while processing the request");
break;
case DiscoveryListener.SERVICE_SEARCH_NO_RECORDS:
LOG.info(rd + ": No records were found during the service search");
break;
case DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
LOG.warning(rd + ": The device specified in the search request could not be reached or the local device could not establish a connection to the remote device");
break;
default:
LOG.warning(rd + ": Unknown Response Code - " + respCode);
break;
}
if (waitForDevices != null)
waitForDevices.countDown();
}
public void servicesDiscovered(int transID, ServiceRecord[] srs) {
LOG.info("Services discovered in transaction " + transID + " : " + srs.length);
for (ServiceRecord sr : srs) {
LOG.info(sr.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false));
servicesDiscovered.add(sr);
}
}
}
public static void main(String[] args) {
new Test().connect();
}
}
I had the same problem while connecting to a Bluetooth earpiece. Like you I was also searching for more than one service at a time and It always returned SERVICE_SEARCH_DEVICE_NOT_REACHABLE. So, I tried searching for only one service and it worked. So, try modifying your code as:
...
private static final UUID[] UUIDS = new UUID[] {new UUID(0x0003)}

Categories

Resources