# Publish & Subscribe

GreenLightning allows behaviors to communicate with each other using PubSub (short for Publish and Subscribe). One behavior can subscribe to a topic and thus listen to any messages coming from other behaviors about the same topic.&#x20;

GreenLightning also has the concept of **Private Topics** - topics between behaviors are discovered at start, and a direct private connection between those behaviors is established, preventing other behaviors from listening if they do not subscribe to the same topic.

## PubSub Example

Below is a very simple PubSub example. The `GreetingBehavior` will send out a greeting message to the topic "Greet" and publish another greeting if it receives a "SayHello" message. The `ExampleBehavior` will listen to the greeting message and send out the initial "SayHello" message.

We demonstrate usage of the default `PubSubListener` (filter topics manually using if-else or switch-case) and `PubSubMethodListener` (direct method call, no branching logic needed).

In our main file, we will simply register the behaviors and add their corresponding subscriptions:

{% code title="PubSub.java" %}

```java
public class PubSub implements GreenApp
{
    @Override
    public void declareConfiguration(Builder c) {
    }

    @Override
    public void declareBehavior(GreenRuntime runtime) {
       // Create a pubSub listener that will broadcast a message if prompted
       runtime.addPubSubListener(new GreetingBehavior(runtime, "Greet"))
                           // We want to know when someone is asking for a greeting.
                            .addSubscription("SayHello");
       
       // Create another behavior that will ask for a Hello on start up and 
       // listen to it.
       ExampleBehavior example = new ExampleBehavior(runtime, "SayHello");
       runtime.registerListener(example)
                           // We want to know when someone greets us, so subscribe
                           .addSubscription("Greet", example::listenToGreeting)
                           // This just demonstrates multiple subscriptions are simpler using
                           // PubSubMethodListener instead of PubSubListener
                           .addSubscription("AnExample", example::anotherMessage);
    }
}
```

{% endcode %}

In `GreetingBehavior.java,` we create a `PubSubFixedTopicService` to publish our message:

{% code title="GreetingBehavior.java" %}

```java
public class GreetingBehavior implements PubSubListener {
   private final PubSubFixedTopicService channel;
   
   public GreetingBehavior(GreenRuntime runtime, CharSequence publishTopic) {
      // Create a channel based on topic passed in that we will publish to
      this.channel = runtime.newCommandChannel().newPubSubService(publishTopic.toString()); 
   }

   // We have receive someone asking for a greeting, so send it!
   @Override
   public boolean message(CharSequence topic, ChannelReader payload) {
      //Note if this behavior is subscribed to more than 1 topic we will need
      //to branch here based on the value of topic.    
      return channel.publishTopic(w -> w.append("Hello World!"));
   }
}
```

{% endcode %}

In `ExampleBehavior.java`, we create another `PubSubFixedTopicService` and use it to publish our given topic on start (we are asking for a Greeting). Then, we have the listenToGreeting method as defined in `PubSub.java` listening to any new greetings:

{% code title="ExampleBehavior.java" %}

```java
public class ExampleBehavior implements PubSubMethodListener, StartupListener {
    private final PubSubFixedTopicService channel;
    
    public ExampleBehavior(GreenRuntime runtime, CharSequence publishTopic) {
       // Create a new command channel that we will use to ask for a greeting (SayHello topic).
       this.channel = runtime.newCommandChannel().newPubSubService(publishTopic.toString());
    }
    
    @Override
    public void startup() {
        // On startup, let's ask for a greeting!
        channel.publishTopic();
    }
    
    public boolean listenToGreeting(CharSequence topic, ChannelReader payload) {
        // We received a greeting, so listen to it
        System.out.println("Received a greeting: " + payload.readUTF());
        return true; // if you were to return false, you will receive the same message again next time
    }
    
     public boolean anotherMessage(CharSequence topic, ChannelReader payload) {
         // Do nothing here, it's just an example.
         return true;
     }
}
```

{% endcode %}

### Private Topics

Private Topics (always enabled) allow direct communication between behaviors without having to dispatch through a central router, improving performance and security.

**However**, you may *not* want Private Topics for certain topics (see warning below). You can use the method `definePublicTopics` on `Builder`:

```java
@Override
public void declareConfiguration(Builder config) {
   // For our example above, this would disable dirct communication between
   // ExampleBehavior and GreetingBehavior. The messages would first go through
   // a grand dispatch before arriving at targeted subscribers.
   config.definePublicTopics("Greet", "SayHello");
}
```

{% hint style="warning" %}
**Note that subscribing to a private topic at runtime is not possible.** You will have to explicitly declare this topic public if you know that it will be dynamically subscribed to at a later point.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://oci-pronghorn.gitbook.io/greenlightning/chapter-5-publish-and-subscribe/example.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
