Я, вероятно, что-то делаю не так, но вот что происходит:
Я регистрирую слушателя, жду, когда он будет вызван, и когда он выполнит и вызовет Vector.clear (), он заблокируется. Проблема возникает в методе pipeMsgEvent, здесь это не очень дружелюбный код (если хотите, перейдите непосредственно к строкам «это важно»):
public class JxtaCustomer implements PipeMsgListener {
public static final int ANSWER_OK = 0;
public static final int ANSWER_TIMEOUT =-1;
public static final int ANSWER_NOT_ASKED =-2;
public static final int ANSWER_WORKING =-3;
public static final int REQ_SENT = 0;
public static final int REQ_INV_PIPE_ID =-1;
public static final int REQ_INV_PIPE_IO =-2;
public static final int REQ_INV_GROUP_ID =-3;
protected int answer;
protected JxtaGenericAdvertisement serviceAdv = null;
protected JxtaNode ThePeer = null;
JxtaBiDiPipe myBiDiPipe = null;
protected Vector<Entry> output = null;
public JxtaCustomer(JxtaGenericAdvertisement adv, JxtaNode peer)
{
ThePeer = peer;
serviceAdv = new JxtaGenericAdvertisement((Element)adv.getDocument(new MimeMediaType("text/xml")));
answer = ANSWER_NOT_ASKED;
Vector<Entry> output = new Vector<Entry>();
}
public void pipeMsgEvent(PipeMsgEvent event)
{
System.out.println("It Works! Uhuuu");
// We received a message
Message message = event.getMessage();
System.out.println("Lets GO! Uhuuu");
Message.ElementIterator elIt = message.getMessageElementsOfNamespace( serviceAdv.getName() );
System.out.println("A little bit more");
answer = ANSWER_WORKING;
System.out.println("enter");
// This is important: Here I get stuck, "clear"
// never appears on the screen
output.clear();
System.out.println("clear");
while (elIt.hasNext()) {
MessageElement mElem = elIt.next();
System.out.println(mElem.getElementName() + " " + mElem.toString());
output.add( new Entry( mElem.getElementName(), mElem.toString() ) );
}
System.out.println("leave");
answer = ANSWER_OK;
}
public int sendRequest(Vector<Entry> params)
{
try {
// Creating Pipe Advertisement
String pipeAdvType = PipeAdvertisement.getAdvertisementType();
PipeAdvertisement pipeAd = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(pipeAdvType);
URI pipeURI = new URI(serviceAdv.getPipeID());
pipeAd.setPipeID( IDFactory.fromURI(pipeURI) );
pipeAd.setType(PipeService.UnicastType);
pipeAd.setName(serviceAdv.getName() + " Service Pipe");
pipeAd.setDescription("Created by " + serviceAdv.getName());
// Creating Group
JxtaGroup jxgp = ThePeer.getGroupFromID( serviceAdv.getGroupID() );
if (null == jxgp)
return REQ_INV_GROUP_ID;
PeerGroup group = jxgp.getPeerGroup();
if (null == group)
return REQ_INV_GROUP_ID;
// This is important: In the JxtaBiDiPipe call I register
// the callback, while I have access to the code, I think
// the problem is in my code
myBiDiPipe = new JxtaBiDiPipe( group, pipeAd, 30000, this);
if (myBiDiPipe.isBound()) {
Thread.sleep(500);
Message myMessage = new Message();
if (0 == params.size())
params.add( new Entry("dummy", "null") );
for (int i=0; i<params.size(); i++) {
String Key = params.get(i).getKey();
String Value = params.get(i).getValue();
StringMessageElement strMsgElem = new StringMessageElement( Key, Value, null);
myMessage.addMessageElement( serviceAdv.getName(), strMsgElem);
}
myBiDiPipe.sendMessage(myMessage);
answer = ANSWER_TIMEOUT;
return REQ_SENT;
}
} catch (URISyntaxException e){
e.printStackTrace();
return REQ_INV_PIPE_ID;
} catch (IOException e) {
return REQ_INV_PIPE_IO;
} catch (Exception e) {
e.printStackTrace();
}
return REQ_INV_PIPE_IO;
}
public Vector<Entry> getResponse()
{
Vector<Entry> results = new Vector<Entry>();
if (ANSWER_OK != answer)
return results;
// This is important: I always call "getState()" and check its value
// before calling this method, so you can say it's guaranteed to be
// called after answer = ANSWER_OK, which never happens because of the
// lock
for (int i=0; i<output.size(); i++)
results.add( output.get(i) );
return results;
}
public int getState()
{
int count = 10;
return answer;
}
}
Я всегда создаю JxtaCustomer следующим образом:
JxtaCustomer customer = new JxtaCustomer(adv, ThePeer);
Vector<Entry> params = new Vector<Entry>();
params.add( new Entry("key1", "value1") );
params.add( new Entry("key2", "value2") );
customer.sendRequest(params);
while(JxtaCustomer.ANSWER_OK != customer.getState()) {
// I was actually using synchronized locks and timed waits
// but since I'm stuck there I'm using this nonsense instead
}
Vector<Entry> response = customer.getResponse();
Вот где в коде я называю «спать», «ждать» или я создаю «синхронизированный» (последний никогда не бывает)
$ grep synchronized $(find . -name "*.java")
$ grep sleep $(find . -name "*.java")
./Src/net/ubi/jxta/JxtaCustomer.java: Thread.sleep(500);
$ grep wait $(find . -name "*.java")
./App/ExampleServices/SimpleSigner.java: boolean waiting = false;
./App/ExampleServices/SimpleSigner.java: waiting = true;
./App/ExampleServices/SimpleSigner.java: return (waiting && JxtaCustomer.ANSWER_OK == customer.getState());
./App/ExampleServices/SimpleSigner.java: if (!waiting)
./App/ExampleServices/SimpleSigner.java: waiting = false;
./App/ExampleServices/SimpleSigner.java: return "Error: Response not ready, wait more time\n";