Skip to content
This repository has been archived by the owner on Jun 7, 2021. It is now read-only.

Commit

Permalink
Copy over ribbon test to ribbon-secured, and launch a keycloak.
Browse files Browse the repository at this point in the history
Does not actually test anything yet. Nor is it secure.
Checkpoint! Checkmate! Matey.
  • Loading branch information
bobmcwhirter committed Dec 10, 2015
1 parent 7b40568 commit 4137b11
Show file tree
Hide file tree
Showing 29 changed files with 1,009 additions and 749 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -14,3 +14,5 @@ verify.log
log
jaxrs/.DS_Store
.DS_Store
.db

3 changes: 3 additions & 0 deletions pom.xml
Expand Up @@ -165,6 +165,9 @@
<module>transactions</module>
<module>vaadin</module>
<module>ribbon</module>
<module>ribbon-secured</module>

<module>keycloak-server</module>
<!--
<module>docker-jaxrs-app</module>
<module>kitchensink-html5-mobile</module>
Expand Down
54 changes: 39 additions & 15 deletions ribbon-secured/README.md
@@ -1,15 +1,12 @@
# Multiple services plus NetFlixOSS Ribbon

> NOTE: This example will not work yet, as it relies upon a patch
> in the upstream of WildFly not yet available in a released version.
> Please raise any issues found with this example in this repo:
> https://github.com/wildfly-swarm/wildfly-swarm-examples
>
> Issues related to WildFly Swarm core should be raised in the main repo:
> https://github.com/wildfly-swarm/wildfly-swarm/issues
The beginnings of a multi-service example.
## Services

Two services exist:

Expand All @@ -20,27 +17,54 @@ The `time` service simply returns the current time as a JSON map
with fields for hour, minute, second, etc.

The `events` service queries the `time` service, and returns a list of
currently on-going events. Currently, it just generates a list of events
that started at the top of the current hour.
currently on-going events.

Each of these services may be accessed with a simple HTTP `GET` request.
For example, the `time` service:

$ curl http://127.0.0.1:8081
{"s":5,"D":3,"ms":647,"tz":"America/New_York","h":10,"Y":2015,"M":12,"m":37}

In addition, the `event` service will accept an HTTP `POST` request with JSON data
specifying the event type. Every `GET` or `POST` request to the `event` service
generates a new event.

## Front End

There is a simple JAX-RS front end that uses the `ribbon-webapp` fraction to
communicate with the services. The web site displays the current Ribbon topology,
and provides a simple button-based UI to `GET` or `POST` messages to the Ribbon
services.

## Try it Out

Build and run the time service:
First, start up the front end, so you can watch the Ribbon topology get updated
in real time. Open a terminal window.

$ cd frontend
$ mvn wildfly-swarm:run

Then open a browser to `http://127.0.0.1:8080`. There will be nothing to see there
yet. Leave this window open and visible while you bring up the two services.

Open another terminal window to build and run the time service:

$ cd time
$ mvn -Djboss.http.port=8081 wildfly-swarm:run

Maybe run it twice:
You should see the Ribbon topology update in the browser as the time service
comes up. Now, open another terminal window, and run the `time` service again,
but this time give it a different port number. Notice how the web UI updates
itself as the service comes up.

$ cd time
$ mvn -Djboss.http.port=8082 wildfly-swarm:run

Then run the events service, which consumes the time service(s):
Finally, open yet another terminal window and run the events service,
which consumes the time service(s). Again, note the UI changes.

$ cd events
$ mvn wildfly-swarm:run

Then

* http://localhost:8080/

Kill and restart one or both of the `time` services, and witness how stuff
behaves.
Now you can kill and restart one or both of the `time` services, and witness the
UI changes. You can also `GET` time and event service data, and `POST` new events.
10 changes: 5 additions & 5 deletions ribbon-secured/events/pom.xml
Expand Up @@ -10,15 +10,15 @@

<parent>
<groupId>org.wildfly.swarm.examples</groupId>
<artifactId>wildfly-swarm-examples-ribbon-secured-parent</artifactId>
<version>1.0.0.Alpha02-SNAPSHOT</version>
<artifactId>examples-ribbon-secured-parent</artifactId>
<version>1.0.0.Alpha6-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>

<artifactId>wildfly-swarm-example-ribbon-secured-events</artifactId>
<artifactId>example-ribbon-secured-events</artifactId>

<name>WildFly Swarm Examples: Netflix Ribbon - Secured - Events</name>
<description>WildFly Swarm Examples: Netflix Ribbon - Secured - Events</description>
<name>WildFly Swarm Examples: Netflix Ribbon Secured: Events</name>
<description>WildFly Swarm Examples: Netflix Ribbon Secured: Events</description>

<packaging>jar</packaging>

Expand Down
@@ -0,0 +1,23 @@
package org.wildfly.swarm.examples.netflix.ribbon.events;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

/**
* @author Lance Ball
*/
@Provider
public class CORSFilter implements ContainerResponseFilter {
public void filter(ContainerRequestContext paramContainerRequestContext,
ContainerResponseContext paramContainerResponseContext)
throws IOException {
paramContainerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
paramContainerResponseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
paramContainerResponseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
paramContainerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
paramContainerResponseContext.getHeaders().add("Access-Control-Max-Age", "1209600");
}
}
@@ -0,0 +1,37 @@
package org.wildfly.swarm.examples.netflix.ribbon.events;

import java.util.Map;

/**
* @author Lance Ball
*/
public class Event {
private int id;
private String name;
private Map timestamp;


public Map getTimestamp() {
return timestamp;
}

public void setTimestamp(Map timestamp) {
this.timestamp = timestamp;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
@@ -1,16 +1,5 @@
package org.wildfly.swarm.examples.netflix.ribbon.events;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -19,23 +8,46 @@
import io.netty.buffer.ByteBufInputStream;
import rx.Observable;

import javax.ws.rs.*;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;

/**
* @author Bob McWhirter
*/
@Path("/")
public class EventsResource {

private final TimeService time;
private static final ArrayList<Event> EVENTS = new ArrayList<>();

public EventsResource() {
this.time = TimeService.INSTANCE;
}

@GET
@Produces("application/json")
@Produces(MediaType.APPLICATION_JSON)
public void get(@Suspended final AsyncResponse asyncResponse) {
Observable<ByteBuf> obs = this.time.currentTime().observe();
Event event = new Event();
event.setName("GET");
recordEvent(event, asyncResponse);
}

@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public void post(Event event, @Suspended final AsyncResponse asyncResponse) {
recordEvent(event, asyncResponse);
}

private void recordEvent(Event event, @Suspended AsyncResponse asyncResponse) {
Observable<ByteBuf> obs = this.time.currentTime().observe();
obs.subscribe(
(result) -> {
try {
Expand All @@ -44,18 +56,20 @@ public void get(@Suspended final AsyncResponse asyncResponse) {
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(new ByteBufInputStream(result));
Map map = reader.readValue(parser, Map.class);
int hour = (int) map.get("h");
List<String> events = new ArrayList<>();
for (int i = 1; i <= 10; ++i) {
events.add("Event #" + i + " at " + hour + ":00");
}
asyncResponse.resume(events);
event.setTimestamp(map);
event.setId(EVENTS.size());
EVENTS.add(event);
asyncResponse.resume(EVENTS);
} catch (IOException e) {
System.err.println("ERROR: " + e.getLocalizedMessage());
asyncResponse.resume(e);
}
},
(err) -> {
System.err.println("ERROR: " + err.getLocalizedMessage());
asyncResponse.resume(err);
});

System.out.println("New event");
}
}
Expand Up @@ -3,7 +3,7 @@
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.wildfly.swarm.container.Container;
import org.wildfly.swarm.jaxrs.JAXRSArchive;
import org.wildfly.swarm.keycloak.Secured;
import org.wildfly.swarm.jgroups.JGroupsFraction;
import org.wildfly.swarm.netflix.ribbon.RibbonArchive;

/**
Expand All @@ -13,12 +13,44 @@ public class Main {

public static void main(String[] args) throws Exception {
Container container = new Container();
JGroupsFraction fraction = new JGroupsFraction()
.defaultChannel( "swarm-jgroups")
.stack( "udp", (s)->{
s.transport( "UDP", (t)->{
t.socketBinding("jgroups-udp");
});
s.protocol("TCP", (p -> {
p.property("bind_port", "9090");
}));
s.protocol("TCPPING", (p)-> {
p.property("initial_hosts", "localhost[9090],localhost[9091],localhost[9092],localhost[9093]")
.property("port_range", "4")
.property("timeout", "3000")
.property("num_initial_members", "4");
});
s.protocol( "FD_SOCK", (p)->{
p.socketBinding( "jgroups-udp-fd" );
});
s.protocol( "FD_ALL" );
s.protocol( "VERIFY_SUSPECT" );
s.protocol( "pbcast.NAKACK2" );
s.protocol( "UNICAST3" );
s.protocol( "pbcast.STABLE" );
s.protocol( "pbcast.GMS" );
s.protocol( "UFC" );
s.protocol( "MFC" );
s.protocol( "FRAG2" );
s.protocol( "RSVP" );
})
.channel( "swarm-jgroups", (c)->{
c.stack( "udp" );
});
container.fraction(fraction);

JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);
deployment.addPackage(Main.class.getPackage());
deployment.addPackage( Main.class.getPackage() );
deployment.addAllDependencies();
deployment.as(Secured.class)
.protect()
.withRole("*");
deployment.as( RibbonArchive.class ).setApplicationName( "events" );
container.start().deploy(deployment);
}
}
@@ -1,17 +1,22 @@
package org.wildfly.swarm.examples.netflix.ribbon.events;

import com.netflix.ribbon.Ribbon;
import com.netflix.ribbon.RibbonRequest;
import com.netflix.ribbon.proxy.annotation.*;
import com.netflix.ribbon.proxy.annotation.Http;
import com.netflix.ribbon.proxy.annotation.Hystrix;
import com.netflix.ribbon.proxy.annotation.ResourceGroup;
import com.netflix.ribbon.proxy.annotation.TemplateName;
import io.netty.buffer.ByteBuf;
import org.wildfly.swarm.netflix.ribbon.secured.SecuredRibbon;

import java.sql.Time;

/**
* @author Bob McWhirter
*/
@ResourceGroup( name="time" )
public interface TimeService {

TimeService INSTANCE = SecuredRibbon.from( TimeService.class );
TimeService INSTANCE = Ribbon.from(TimeService.class);

@TemplateName("currentTime")
@Http(
Expand Down
10 changes: 0 additions & 10 deletions ribbon-secured/events/src/main/resources/keycloak.json
@@ -1,10 +0,0 @@
{
"realm": "sample",
"realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhQ01r8e0wK6uiwCab2WXTK8xdbg7Ddg9vWPr1LJCcrB4pFZS3BvSeU4dLnlHzIK2NQhs++nkGMfk/rCb+DJ6xXMfRhr89FTgoKsm4xZCtocpuLdmMljlzezAJuvBBw+8gxBY5JhpDt99bhyCLK/wBS9dAmgB7kW6uDkTx8uVLuiUMi91xE/REaNR9sJMCAXbtre6Ij/YqeUc8jo3DVaxjFmL7l/48OMcRgtpd93lxxbC9VuSO/H/jszKJ8DrfJRyrOFzfcorxJ3HadSqPWDZwxNt1VjnxXJEUA/2l/FqtinE5e+sGEUXIRo/50jKaV5w03YX9pmFrHA+p2HzJc1qdQIDAQAB",
"auth-server-url": "http://localhost:9191/auth",
"ssl-required": "none",
"resource": "sample-client",
"credentials": {
"secret": "8336d476-6097-40c7-bd57-47b4c9f50b76"
}
}

0 comments on commit 4137b11

Please sign in to comment.