Giter Club home page Giter Club logo

Comments (11)

ljnelson avatar ljnelson commented on August 25, 2024

It's worth noting that this is possible with existing features, if a bit cumbersome. Typing syntax off the cuff, so I may make mistakes but I think you'll get the idea:

routingBuilder.get((req, res) -> {
  if (isSuitable(req, res)) {
    // handle it yourself here
  } else {
    // punt
    req.next();
  }
});

Here, we register an (anonymous) Handler for all GETs that calls some mythical isSuitable method. If that "passes", then we do one thing; if it "fails" then we let control pass to the next Handler in the chain (req.next()). This isSuitable method has access, of course, to everything you can "reach" from a ServerRequest, so that should cover it.

It might be worthwhile? maybe? to add a convenience method that takes a BiPredicate<ServerRequest, ServerResponse> and a Handler to execute if the Predicate passes (or some other similar recipe). But we can do what you want to do above already.

from helidon.

spericas avatar spericas commented on August 25, 2024

Yes, in principle, applications can provide handlers that match all requests and then do the routing on their own. However, this is far from convenient for developers: routing is one of the reasons to use libraries like Helidon.

OTOH, this is by no means a feature all applications need, so I suggest that we wait and see if the community finds a need for dynamic routing before moving forward.

from helidon.

romain-grecourt avatar romain-grecourt commented on August 25, 2024

Maybe something like this ?

routing.register(String, Function<String, Service>)
routing.httpVerb(String, Function<String, Handler>)

from helidon.

axelsean avatar axelsean commented on August 25, 2024

Here's my use case:

  • I have mini services that are based on objects, they provide CRUD.
  • Each of these will generate API aggregation meta data so that the data, view (UI format) and drop downs can be read in a single server round trip.
  • My service is a Consumer of the API Aggregation data
  • The URL will have path variable(s) to be passed - which are part of the meta data - matching these to the path specification is important

Thus this all happens way after the server is started.

from helidon.

romain-grecourt avatar romain-grecourt commented on August 25, 2024

Can you help me understand a little more your use-case ?

IIUC your application is exposing data from kafka as a single CRUD REST API ; your code is organized using Helidon WebServer services (i.e io.helidon.webserver.Service).

The need for dynamic service matching would be required if you need to match specific service implementations per request (path, header etc).

Is this your particular scenario ?

Otherwise if you have a generic CRUD service you can register it using wildcard path parameter(s).

E.g.

rules.register("/{+}/", new MyCRUDService())

from helidon.

romain-grecourt avatar romain-grecourt commented on August 25, 2024

@spericas @ljnelson

How about having a Function<ServerRequest, Service> approach, we'd provide a sub-interface to document things properly:

interface ServiceMatcher extends Function<ServerRequest, Service> {
  /**
    * javadoc blah blah
    */
  Service apply(ServerRequest request);
}

We'd overload Routing.rules

interface Routing.Rules {
  // ...
  register(String path, ServiceMatcher serviceMatcher);
}

An example would look like what @spericas described:

.register("/service/{version}", req -> isV1(req.path()) ? new ServiceV1() : new CurrentService())
.build();

What to do with null when returned ? It would be the absence of routes, thus would result in 404.
I'd like to have something like this as document equivalent:

public final class NoOpService implements Service {
  update(Routing.rules rules) {
    // do nothing
  }
}

from helidon.

spericas avatar spericas commented on August 25, 2024

@romain-grecourt Something like that should work. Perhaps we should use the term ServiceLocator since a lot of people are familiar with that JAX-RS concept.

from helidon.

axelsean avatar axelsean commented on August 25, 2024

Can you help me understand a little more your use-case ?

IIUC your application is exposing data from kafka as a single CRUD REST API ; your code is organized using Helidon WebServer services (i.e io.helidon.webserver.Service).

Yes I have 1 - n Microservices supplying this, each accessible directly eg (final part of URI only)

  • .../pipe/1232113
  • .../manhole/737373
  • .../workOrder/86343

I also have meta data that is predictable such that I can create an aggregate service that would call well known endpoints, eg

  • .../view/pipe/editView
  • .../pipe/132213
  • .../lookups/pipeStatus

The items (pipe/manhole) are not known when the system is deployed, and they canid fact be added dynamically, hence the need to send the metadata to an aggregator service which will dynamically add the routing, and then later calls the URI's and aggregates the data into a single response.

I think it's possible to do this by creating a service that is a Kafka consumer - for the meta data messages, then stopping and restarting the web server each time a new message is received (which adds to the routes needed), this seems messy however

The need for dynamic service matching would be required if you need to match specific service implementations per request (path, header etc).

Is this your particular scenario ?

Otherwise if you have a generic CRUD service you can register it using wildcard path parameter(s).

E.g.

rules.register("/{+}/", new MyCRUDService())

from helidon.

romain-grecourt avatar romain-grecourt commented on August 25, 2024

@axelsean Thanks for the additional explanations. I understand how your "aggregator service" could leverage the "service locator" feature being discussed.

But couldn't you also do this with path params and static routes ?
What if the aggregator service uses routes like these:

rules.get("/view/{item}/editView", this::handler1)
        .get("/{item}/{id}", this::handler2)
        .get("/lookups/{item}Status", this::handler3)
        .build()

from helidon.

romain-grecourt avatar romain-grecourt commented on August 25, 2024

@spericas +1 for ServiceLocator

from helidon.

spericas avatar spericas commented on August 25, 2024

@axelsean Thanks for the additional explanations. I understand how your "aggregator service" could leverage the "service locator" feature being discussed.

But couldn't you also do this with path params and static routes ?
What if the aggregator service uses routes like these:

rules.get("/view/{item}/editView", this::handler1)
        .get("/{item}/{id}", this::handler2)
        .get("/lookups/{item}Status", this::handler3)
        .build()

I suspect the problem with this approach is that handlers like this::handler1 would need to include logic for all items: manhole, pipe, etc. Architecturally, a service per item kind would make more sense.

from helidon.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.