Skip to main content

Custom Advertisement Discovery

7 replies [Last post]
ggeorgak
Offline
Joined: 2005-08-14

Hello, I use the following code to create a custom advertisement:


package chatadv;

import net.jxta.document.AdvertisementFactory;
import net.jxta.document.Advertisement;
import net.jxta.document.MimeMediaType;
import net.jxta.document.Document;
import net.jxta.document.Element;
import net.jxta.document.StructuredDocument;
import net.jxta.document.StructuredDocumentFactory;
import net.jxta.id.ID;
import net.jxta.id.IDFactory;
import net.jxta.peer.PeerID;
import java.net.URI;

public class ChatAdv extends Advertisement
{
static
{
net.jxta.document.AdvertisementFactory.registerAdvertisementInstance(getAdvertisementType(),new ChatAdv.Instantiator());
}
public static final String nameKey="Name";
public static final String idKey="ID";
public static final String PeerIDKey="PeerID";
public static final String preferredAddressKey= "PreferredAddress";
public static final String indexFields[] = new String[] {idKey,nameKey,PeerIDKey,preferredAddressKey};

private String name;
private String PeerID;
private String preferredAddress;

public static final class Instantiator implements AdvertisementFactory.Instantiator
{
public String getAdvertisementType()
{
return ChatAdv.getAdvertisementType();
}
public Advertisement newInstance()
{
return new ChatAdv();
}

public Advertisement newInstance(Element element)
{
ChatAdv adv = new ChatAdv();

Element elem = (Element) element.getChildren(nameKey).nextElement();
if (elem !=null && elem.getValue() != null)
{
adv.setName(elem.getValue().toString());
}

elem = (Element) element.getChildren(PeerIDKey).nextElement();
if (elem !=null && elem.getValue() != null)
{
adv.setPeerID(elem.getValue().toString());
}

elem = (Element) element.getChildren( preferredAddressKey ).nextElement();
if (elem !=null && elem.getValue() != null)
{
adv.setPreferredAddress(elem.getValue().toString());
}
return adv;
}
}

public ChatAdv()
{
super();
}

public void setName(String name)
{
this.name = name;
}

public String getName()
{
return name;
}

public static String getAdvertisementType()
{
return "jxta:chatadv";
}

public final String getBaseAdvType()
{
return getAdvertisementType();
}
public Document getDocument(MimeMediaType mimeMediaType)
{
StructuredDocument doc = StructuredDocumentFactory.newStructuredDocument( mimeMediaType, getAdvertisementType() );

Element elem = doc.createElement(nameKey,name);
doc.appendChild(elem);
elem = doc.createElement(PeerIDKey,PeerID);
doc.appendChild(elem);
elem = doc.createElement(preferredAddressKey,preferredAddress);
doc.appendChild( elem );
return doc;
}

public ID getID()
{
try
{
return (PeerID) IDFactory.fromURI(new URI(PeerID));
}
catch(Exception e)
{
return null;
}
}

public String[] getIndexFields()
{
return indexFields;
}

public String getPreferredAddress()
{
return preferredAddress;
}
public void setPreferredAddress(String preferredAddress)
{
this.preferredAddress=preferredAddress;
}

public String getPeerID()
{
return PeerID;
}
public void setPeerID(String peerID)
{
this.PeerID=peerID;
}

public boolean equals(Object target)
{
if (target instanceof ChatAdv)
{
return ((ChatAdv)target).getID().equals(getID());
}
else
{
return false;
}
}
public int hashcode()
{
return getID().hashCode();
}

public Object clone()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException impossible)
{
return null;
}
}
}

And then I remote publish it using:


netPeerGroup.getDiscoveryService().remotePublish(myChatAdv);

But I am unable to find it using:


netPeerGroup.getDiscoveryService().getRemoteAdvertisements(null,DiscoveryService.ADV,null,null,10);

which searches for all ADV types and plus I cannot discovery it using:


netPeerGroup.getDiscoveryService().getRemoteAdvertisements(null,DiscoveryService.ADV,ChatAdv.nameKey,"someusername",10);

Any help would be greatly appreciated.

PS: Sorry for the messy code, I do not know how to indent it in the post. If someone knows please let me know.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
ggeorgak
Offline
Joined: 2005-08-14

Well this is weird!

Test one:

I created a private net peer group where I controlled the rendezvous peer. If I register the ChatAdv advertisement by creating a "dummy" rendezous ChatAdv (thus this code runs:

class ChatAdv extends Adverstisement
{
static
{
net.jxta.document.AdvertisementFactory.registerAdvertisementInstance(getAdvertisementType(),new ChatAdv.Instantiator());
}

the discovery works!

Test two:

Now this is what the proper behavior should be. Before I remotePublish the adv I publish it locally. So the discovery service is able to find it both in a private and public netpeergroup! This should be the expected behavior since remotely publishing an adv really means creating a srdi index for that adv so the adv needs to be available in some peer. This sounds logical but how test one managed to succeed???

Waiting for comments...

alexhealing
Offline
Joined: 2005-11-01

Hi ggeorgak,

I'm not sure if I understand your last post correctly. Did you get the Custom Advertisements to be discovered correctly?

I'm having trouble doing just that. I can easily discover the CustomAdv locally on the peer that publishes it but it doesn't seem to be accessible from other peers.

Is there some special case of rendezvous peers and net peer groups which prevents it from working? I'm going to try a private net peer group as you suggested but don't see how that would make any difference.

Please, if you could give shed any light on the subject it would be a great help. I am still confused about various things including the use of the getID() method in the Advertisement class - when and why is it called? Also, how the indexFields[] used?

Many thanks...

bgrieder
Offline
Joined: 2006-12-02

Just in case some other guy like me needs this answer on this (and does not want to waste a few hours like me):

The peer looking for a remote custom advertisement MUST register the advertisement Instantiator with the Advertisement Factory for that Advertisement type.

e.g.

static{
AdvertisementFactory.registerAdvertisementInstance(
CustomAdvertisement.getAdvertisementType(),
SubscriptionAdvertisement.getInstantiator()
);
}

where getInstantiator returns an instance of a class that implements the Instantiator interface for that Advertisement.

Bruno Grieder

rille
Offline
Joined: 2004-11-14

Did you get it to work to 100%?

I also have some issues with finding advertisements. I suspect rendevous can have something to do with that as well. After I publish an ADV and starts another instance it's not 100% sure that my disco will find it. Clearly annoying. :)

Have you tried other types af adv?
I will post the code I use for creating a new PipeAdv and you can try to publish that instead and see if you can find it.

[code]
public class newPipeAdvertiseFactory {

/**
* Creates a new PipeAdvertisement
*
* @return PipeAdvertisement
*/
public static PipeAdvertisement newPipeAdvertisement(PeerGroup peerGroup, String name) {
PipeAdvertisement pipeAdv = (PipeAdvertisement) AdvertisementFactory.newAdvertisement
("jxta:PipeAdvertisement");
pipeAdv.setPipeID(newIDFactory.createPipeID(peerGroup.getPeerGroupID(), name, "BombermanPipe"));
pipeAdv.setName("BomberManGamePipeAdv");
pipeAdv.setType("JxtaUnicast");
pipeAdv.setDescription(name);
return pipeAdv;
}

/**
* Creates a new Unique PipeAdvertisement for this Peer
*
* @return PipeAdvertisement
*/
public static PipeAdvertisement newPeerUniquePipeAdvertisement(PeerGroup peerGroup, String name) {
PipeAdvertisement pipeAdv = (PipeAdvertisement) AdvertisementFactory.newAdvertisement
("jxta:PipeAdvertisement");
pipeAdv.setPipeID(newIDFactory.createPipeID(peerGroup.getPeerGroupID(), name, peerGroup.getPeerID().toString()));
pipeAdv.setName("BomberManGamePipeAdv");
pipeAdv.setType("JxtaUnicast");
pipeAdv.setDescription(name);
return pipeAdv;
}

/**
* Prints an Advertisement
*
* @param adv the Advertise you want to print
*/
public static void printAdvertisement(Advertisement adv) {
StructuredTextDocument doc = (StructuredTextDocument)
adv.getDocument(MimeMediaType.TEXT_DEFAULTENCODING);
StringWriter out = new StringWriter();
try {
doc.sendToWriter(out);
System.out.println(out.toString());
out.close();
} catch (IOException e) { /* ignore error for now*/ }
}

}

public class newIDFactory {

/**
* Creates a new PeerGroupID
* Used since all clients needs to be able to create and jojn the same main group
*
* @param parentID ID of the default group before joining
* @param clearTextID text id (can be given as string)
* @param function function (can be given as string)
* @return PeerGroupID
*/
public static final PeerGroupID createPeerGroupID(PeerGroupID parentID, String clearTextID, String function) {
byte[] digest = generateHash(clearTextID, function);
PeerGroupID peerGroupID = IDFactory.newPeerGroupID(parentID, digest);
return peerGroupID;
}

/**
* Creates a new PipeID
* Used since we want the same ID on our pipes according to group
*
* @param parentID ID of the default group before joining
* @param clearTextID text id (can be given as string)
* @param function function (can be given as string)
* @return PipeID
*/
public static final PipeID createPipeID(PeerGroupID parentID, String clearTextID, String function) {
byte[] digest = generateHash(clearTextID, function);
PipeID pipeID = IDFactory.newPipeID(parentID, digest);
return pipeID;
}

/**
* Returns a MD5 representation of the given string
*
* @param clearTextID text id (can be given as string)
* @param function function function (can be given as string)
* @return byte[]
*/
private static final byte[] generateHash(String clearTextID, String function) {
String id;

if (function == null) {
id = clearTextID;
} else {
id = clearTextID + "~" + function;
}
byte[] buffer = id.getBytes();

MessageDigest algorithm = null;

try {
algorithm = MessageDigest.getInstance("MD5");
} catch (Exception e) {

return null;
}

// Generate the digest.
algorithm.reset();
algorithm.update(buffer);

try {
byte[] digest1 = algorithm.digest();
return digest1;
} catch (Exception de) {

return null;
}
}

}

[/code]

And for testing if you can find it later:

[code]
disco.getRemoteAdvertisements(null
, DiscoveryService.ADV
, "Name"
, "BomberManGamePipeAdv", 10, null);

[/code]

I'm trying to write a Jxta Bomberman game but it isn't going very well.
Everytime I think something works something else goes amiss. Right now I'm having problems publishing PipeAdvs.
Other instances of my app can't always see them =(
It's not easy to be ignorant... ;)

/Rickard

xiegang
Offline
Joined: 2004-07-24

I have a problem about how to get the peer Id of the JXME client.
the tutorial from the www.jxta.org mentions that:
When a mobile client connects to a JXTA network, it first requests a peer identifier. The relay assigns a peer identifier in response to the request, and the client uses the peer identifier in subsequent communication.

So, I send a request from the client to the relay which is running on the same PC.The request is like this:
GET /unknown-unknown?0,-1,http://172.16.0.37:2481/
EndpointService:jxta-NetGroup/
uuid-DEADBEEFDEAFBABAFEEDBABE0000000F05/pid HTTP/1.1
Connection: close
Content-Length: 0
User-Agent: UNTRUSTED/1.0
Host: 172.16.0.37:2481

But, I never get a peer Id.
I'd like to know what's the problem with it?
Thks!

ggeorgak
Offline
Joined: 2005-08-14

Excuse me but obviously you have not used forums before. This thread is about the question I posted above. So the replies should address the above issue. For your question you should start another thread and post it there. Please be more careful in the future.

Giorgis Georgakoudis

xiegang
Offline
Joined: 2004-07-24

I am sorry about this.By the way, could you please help me with my problem?