-
Couldn't load subscription status.
- Fork 216
Java glacier2 callback #624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
5fabbfc
9c199fc
9280a5d
16a7fa0
79b7be0
c374900
1c7d1f8
138e0c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # Gradle generated build files | ||
| bin | ||
| build | ||
| .gradle |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Glacier2 Callback | ||
|
|
||
| This demo shows how to write a client that establishes a session with a Glacier2 router. It also shows how to implement | ||
| callbacks in this client. | ||
|
|
||
| This demo is similar to the [Ice Callback][1] demo, except all communications go through the Glacier router. | ||
|
|
||
| The connection between the client and the Glacier2 router is a "bidir" connection, like in the [Ice Bidir][2] demo: | ||
|
|
||
| ```mermaid | ||
| flowchart LR | ||
| c[Client<br>hosts AlarmClock] --bidir connection--> g[Glacier2 router:4063] | ||
| g --connection1--> s[Server:4061<br>hosts WakeUpService] --connection2--> g | ||
| ``` | ||
|
|
||
| ## Ice prerequisites | ||
|
|
||
| - Install Glacier2. See [Ice service installation]. | ||
|
|
||
| ## Building the demo | ||
|
|
||
| The demo has two Gradle projects, **client** and **server**, both using the [application plugin]. | ||
|
|
||
| To build the demo, run: | ||
|
|
||
| ```shell | ||
| ./gradlew build | ||
| ``` | ||
|
|
||
| ## Running the demo | ||
|
|
||
| Start the Server program in its own terminal: | ||
|
|
||
| ```shell | ||
| ./gradlew :server:run --quiet | ||
| ``` | ||
|
|
||
| Next, start the Glacier2 router in its own terminal: | ||
|
|
||
| ```shell | ||
| glacier2router --Ice.Config=config.glacier2 | ||
| ``` | ||
|
|
||
| > [!TIP] | ||
| > You can also start the Glacier2 router before the server. The order does not matter: the server is identical to the | ||
| > server provided in the [Ice Greeter][1] demo and does not depend on Glacier2. | ||
|
|
||
| Finally, in a separate terminal, start the client application: | ||
|
|
||
| ```shell | ||
| ./gradlew :client:run --quiet | ||
| ``` | ||
|
|
||
| [Application plugin]: https://docs.gradle.org/current/userguide/application_plugin.html | ||
|
|
||
| [1]: ../callback | ||
| [2]: ../bidir | ||
|
Comment on lines
+56
to
+57
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| // Copyright (c) ZeroC, Inc. | ||
|
|
||
| plugins { | ||
| // Apply the application plugin to tell gradle this is a runnable Java application. | ||
| id("application") | ||
|
|
||
| // Apply the Slice-tools plugin to enable Slice compilation. | ||
| id("com.zeroc.slice-tools") version "3.8.+" | ||
|
|
||
| // Pull in our local 'convention plugin' to enable linting. | ||
| id("zeroc-linting") | ||
| } | ||
|
|
||
| dependencies { | ||
| // Add Ice and Glacier2 as implementation dependencies. | ||
| implementation("com.zeroc:ice:3.8.+") | ||
| implementation("com.zeroc:glacier2:3.8.+") | ||
| implementation(project(":util")) | ||
| } | ||
|
|
||
| sourceSets { | ||
| main { | ||
| // Add the AlarmClock.ice file from the parent slice directory to the main source set. | ||
| slice { | ||
| srcDirs("../slice") | ||
| } | ||
| } | ||
| } | ||
|
|
||
| application { | ||
| // Specify the main entry point for the application. | ||
| mainClass.set("com.example.glacier2.callback.client.Client") | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| // Copyright (c) ZeroC, Inc. | ||
|
|
||
| package com.example.glacier2.callback.client; | ||
|
|
||
| import java.time.ZoneOffset; | ||
| import java.time.ZonedDateTime; | ||
| import java.util.concurrent.ExecutionException; | ||
|
|
||
| import com.example.earlyriser.AlarmClockPrx; | ||
| import com.example.earlyriser.WakeUpServicePrx; | ||
| import com.example.util.Time; | ||
| import com.zeroc.Glacier2.CannotCreateSessionException; | ||
| import com.zeroc.Glacier2.PermissionDeniedException; | ||
| import com.zeroc.Glacier2.RouterPrx; | ||
| import com.zeroc.Glacier2.SessionPrx; | ||
| import com.zeroc.Ice.Communicator; | ||
| import com.zeroc.Ice.Identity; | ||
| import com.zeroc.Ice.ObjectAdapter; | ||
| import com.zeroc.Ice.Util; | ||
|
|
||
| class Client { | ||
| public static void main(String[] args) { | ||
| // Create an Ice communicator. We'll use this communicator to create proxies and manage outgoing connections. | ||
| try (Communicator communicator = Util.initialize(args)) { | ||
|
|
||
| // Create a proxy to the Glacier2 router. The addressing information (transport, host and port number) is | ||
| // derived from the value of Glacier2.Client.Endpoints in the glacier2 router configuration file. | ||
| RouterPrx router = RouterPrx.createProxy(communicator, "Glacier2/router:tcp -h localhost -p 4063"); | ||
|
|
||
| // Create a session with the Glacier2 router. In this demo, the Glacier2 router is configured to accept any | ||
| // username/password combination. This call establishes a network connection to the Glacier2 router; the | ||
| // lifetime of the session is the same as the lifetime of the connection. | ||
| SessionPrx session; | ||
| try { | ||
| session = router.createSession(System.getProperty("user.name"), "password"); | ||
| } catch (PermissionDeniedException | CannotCreateSessionException e) { | ||
| System.out.println("Could not create session: " + e.getMessage()); | ||
| return; | ||
| } | ||
|
|
||
| // The proxy returned by createSession is null because we did not configure a SessionManager on the Glacier2 | ||
| // router. | ||
| assert session == null; | ||
|
|
||
| // Obtain a category string from the router. We need to use this category for the identity of | ||
| // server->client callbacks invoked through the Glacier2 router. | ||
| String clientCategory = router.getCategoryForClient(); | ||
|
|
||
| // Create an object adapter with no name and no configuration, but with our router proxy. This object | ||
| // adapter is a "bidirectional" object adapter, like the one created by the Ice/Bidir client application. | ||
| // It does not listen on any port and it does not need to be activated. | ||
| ObjectAdapter adapter = communicator.createObjectAdapterWithRouter("", router); | ||
|
|
||
| // Register the MockAlarmClock servant with the adapter. It uses the category retrieved from the router. | ||
| // You can verify the Ring callback is never delivered if you provide a different category. | ||
| var mockAlarmClock = new MockAlarmClock(); | ||
| AlarmClockPrx alarmClock = AlarmClockPrx.uncheckedCast( | ||
| adapter.add(mockAlarmClock, new Identity("alarmClock", clientCategory))); | ||
|
|
||
| // Create a proxy to the wake-up service behind the Glacier2 router. Typically, the client cannot connect | ||
| // directly to this server because it's on an unreachable network. | ||
| WakeUpServicePrx wakeUpService = WakeUpServicePrx.createProxy( | ||
| communicator, | ||
| "wakeUpService:tcp -h localhost -p 4061"); | ||
|
|
||
| // Configure the proxy to route requests using the Glacier2 router. | ||
| wakeUpService = WakeUpServicePrx.uncheckedCast(wakeUpService.ice_router(router)); | ||
|
|
||
| // Schedule a wake-up call in 5 seconds. This call establishes the connection to the server; incoming | ||
| // requests over this connection are handled by the communicator's default object adapter. | ||
| wakeUpService.wakeMeUp(alarmClock, Time.toTimeStamp(ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(5))); | ||
| System.out.println("Wake-up call scheduled, falling asleep..."); | ||
| try { | ||
| // Wait until the user presses the stop button on the alarm clock. | ||
| mockAlarmClock.stopPressed().get(); | ||
| System.out.println("Stop button pressed, exiting..."); | ||
| } catch (InterruptedException | ExecutionException ex) { | ||
| System.err.println(ex); | ||
| } | ||
|
|
||
|
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // Copyright (c) ZeroC, Inc. | ||
|
|
||
| package com.example.glacier2.callback.client; | ||
|
|
||
| import java.util.concurrent.CompletableFuture; | ||
|
|
||
| import com.example.earlyriser.AlarmClock; | ||
| import com.example.earlyriser.ButtonPressed; | ||
| import com.zeroc.Ice.Current; | ||
|
|
||
| /** | ||
| * MockAlarmClock is an Ice servant that implements Slice interface AlarmClock. | ||
| */ | ||
| class MockAlarmClock implements AlarmClock { | ||
| private boolean _needMoreTime = true; | ||
|
|
||
| private final CompletableFuture<Void> _stopPressed; | ||
|
|
||
| public MockAlarmClock() { | ||
| _stopPressed = new CompletableFuture<>(); | ||
| } | ||
|
|
||
| public CompletableFuture<Void> stopPressed() { | ||
| return _stopPressed; | ||
| } | ||
|
|
||
| // Implements the method ring from the AlarmClock interface generated by the Slice compiler. | ||
| @Override | ||
| public ButtonPressed ring(String message, Current current) { | ||
| System.out.println("Dispatching ring request { message = '" + message + "' }"); | ||
| if (_needMoreTime) { | ||
| System.out.println("Returning " + ButtonPressed.Snooze + " to request more time."); | ||
| _needMoreTime = false; // we only snooze one time | ||
| return ButtonPressed.Snooze; | ||
| } else { | ||
| _stopPressed.complete(null); | ||
| System.out.println("Returning " + ButtonPressed.Stop + " to stop the alarm."); | ||
| return ButtonPressed.Stop; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Config file for glacier2router | ||
|
|
||
| # The client-visible endpoint of the Glacier2 router. | ||
| Glacier2.Client.Endpoints=tcp -p 4063 | ||
|
|
||
| # The server-visible endpoint of the Glacier2 router. | ||
| # You need to configure this endpoint only when your servers make callbacks (call objects implemented by the clients). | ||
| # If you don't use callbacks, don't set this property. | ||
| Glacier2.Server.Endpoints=tcp -h 127.0.0.1 | ||
|
|
||
| # This Glacier router accepts any username/password combination. | ||
| Glacier2.PermissionsVerifier=Glacier2/NullPermissionsVerifier | ||
|
|
||
| # Turn on tracing. | ||
| Glacier2.Client.Trace.Request=1 | ||
| Glacier2.Server.Trace.Request=1 | ||
| Glacier2.Trace.Session=1 | ||
| Glacier2.Trace.RoutingTable=1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| distributionBase=GRADLE_USER_HOME | ||
| distributionPath=wrapper/dists | ||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-all.zip | ||
| networkTimeout=10000 | ||
| validateDistributionUrl=true | ||
| zipStoreBase=GRADLE_USER_HOME | ||
| zipStorePath=wrapper/dists |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reference to 'Ice Greeter' demo is incorrect. Based on the context, this should reference the 'Ice Callback' demo since this Glacier2 demo is similar to the Ice Callback demo mentioned at the beginning.