Skip to content
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

jooby 3: next major release #1712

Closed
jknack opened this issue May 12, 2020 · 57 comments
Closed

jooby 3: next major release #1712

jknack opened this issue May 12, 2020 · 57 comments

Comments

@jknack
Copy link
Member

jknack commented May 12, 2020

This is an open discussion of what we want for Jooby 3.x. For now we will start a discussion here and then cleanup ideas/features to a wiki page (or similar).

Beside is going to be a major release... I'm not planning to break compatibility like we did in 1.x -> 2.x upgrade, so:

  • Web site will keep as it is today: https://jooby.io, same goes for Java package: io.jooby.
  • The 3.x source code will be just a refactor of existing 2.x source code (not an entire rewrite). Unless something really bad/ugly come up, you will be able to upgrade doing a search/replace session.

Some notes I have so far:

  • Review Context API add getter/setter for almost everything (simplify unit test)
  • Keep minimum request/response related method into Context (simply context API)
  • Add getRequest/getResponse method to Context and add all the necessary getter/setter to each of these new Request/Response API
  • Remove bytecode analysis for return types and get back reactive operators (similar to 1.x)
  • Remove asm from jooby core
  • Kotlin Normal route vs Coroutine route try to simplify usage and remove the HandlerContext object. Favor usage of fun some(ctx: Context) and then get("/route", ::some). This probably implies that lambda body route are bind to Context itself
  • Rename FileUpload.destroy to close and make it Closable
  • Value API make them getter friendly
  • Remove runApp. Replace. with new App()
  • Rename Jooby class to WebApp?
  • Use application.logback.xml so we don't have initialization issues

As always, your feedback is welcome

@jknack jknack pinned this issue May 12, 2020
@jknack jknack added this to the 3.0.0 milestone May 12, 2020
@Sayyiditow
Copy link

Sayyiditow commented May 18, 2020

These look good. Can you also include adding of setter methods for the ModelAndView class so we don't have to re-initialize the class in case we are changing the view name for the same route?

Having to do this right now, in stead just set the view name based on the request parameters. Other routes can have multiple such initialization which looks expensive?

get("/", ctx -> {
            ValueNode asyncPage = ctx.query("asyncPage");
            ModelAndView modelAndView;
            if (Boolean.parseBoolean(asyncPage.toString()))
                modelAndView = new ModelAndView("index_async.ftl");
            else
                modelAndView = new ModelAndView("index.ftl");
            
            return modelAndView;
        });

@imeszaros
Copy link
Member

imeszaros commented May 28, 2020

Nice to hear that compatibility with 2.x is kept in mind. We just started to use Jooby 2.x and planning with it for the long run, also planning to migrate our older codebases.

Huge thumbs up for the API refactoring for Contect -> Request + Response!

We ran into some problems with the Guice extension. In Jooby 1.x it was very convenient that you could inject request scoped objects into controllers / services. In Jooby 2.x it's only possible with some custom extensions implementing @RequestScoped and co. similarly to Jooby 1.x.

Could you briefly explain what does return value analysis and ASM in Jooby do?

@jknack
Copy link
Member Author

jknack commented May 28, 2020

Huge thumbs up for the API refactoring for Contect -> Request + Response!

Going to keep Context in 3.x, because feel it is better the single argument handler:

get("/", ctx -> {...})

and not the two arguments

get("/", (req, rsp) -> {...}

There are some method name collision will keeping everything in Context class. In 3.x going to only keep the most frequently used methods in Context class, while less frequently or more specific methods will be available in Request/Response classes. This helps to keep some common code in Context (jooby-core) and force server to implement more simple/basic Request/Response objects.

Could you briefly explain what does return value analysis and ASM in Jooby do?

ASM helps to identify handler return types in lambda/script routes:

get("/rx", ctx -> CompletableFuture.supplyAsync(() -> "..."));

So here ASM find the handler returns a completable future and:

  • Run route handler in EventLoop
  • Attach a completable listener and to send response when ready

Same for other reactive types from: rxjava and reactor
In 3.x this will requires some manual intervention (like in 1.x):

use(new CompletableFutureAdaptor());
get("/rx", ctx -> CompletableFuture.supplyAsync(() -> "..."));

Removing ASM give us:

  • Even faster startup time
  • Reduce memory in class space

@re-thc
Copy link

re-thc commented Jun 8, 2020

Would removing ASM slow performance down?

Would be good to add a jackson alternative such as dsljson since that's been 1 of the bottlenecks in techempower benchmarks :)

Maybe other security options besides a heavy weight like pac4j?

GraalVM aka native mode would be useful in a lot of places but might be a bit of work.

@jknack
Copy link
Member Author

jknack commented Jun 8, 2020

Would removing ASM slow performance down?

A bit on some specific use cases, but not for usage on real application.

Would be good to add a jackson alternative such as dsljson since that's been 1 of the bottlenecks in techempower benchmarks :)

Yea, nothing stop us from using dsljson today. Due it requires an annotation processor, don't think we need to support as Jooby module. I keep jackson in TEB bc is a real library that works for complex use cases. Still, we. could rewrite the benchmark to use. something more lightweight

Maybe other security options besides a heavy weight like pac4j?

Hahaha, feel something similar... but is there any security framework lightweight?

GraalVM aka native mode would be useful in a lot of places but might be a bit of work.

We did some work and got something working with 2.x, slf4j-simple logging and netty (think undertow didn't work). Removing ASM from core (actually from runtime) will help to make Graal image.

@re-thc
Copy link

re-thc commented Jun 8, 2020

Yea, nothing stop us from using dsljson today. Due it requires an annotation processor,

dsljson has a reflection option, which is still quite a bit faster.

but is there any security framework lightweight?

If it's just basic auth or jwt (via e.g. jjwt) then it doesn't really need a "framework".

netty (think undertow didn't work)

Undertow 3 will be a wrapper around netty.

@jknack
Copy link
Member Author

jknack commented Jun 8, 2020

dsljson has a reflection option, which is still quite a bit faster.

cool, I didn't know it.

If it's just basic auth or jwt (via e.g. jjwt) then it doesn't really need a "framework".

Yea, I usually do header auth so never use pac4j. There is a jwt auth module too: https://jooby.io/modules/jwt-session-store/

Undertow 3 will be a wrapper around netty.

Awful/wrong decision is you ask me. Found undertow super fast (faster than netty) and by far lot easy to work than netty. Also, it is a truly option/alternative to netty today. Don't want to be a wrapper over netty.
I believe Undertow API and execution model will be more or less the same (but around netty). Probably going to drop support for Netty when Undertow run on top of it.

@re-thc
Copy link

re-thc commented Jun 8, 2020

Found undertow super fast (faster than netty)

Depends. Netty has more features like OpenSSL support. There's a lot of options that can be turned on. Out of the box Undertow is faster. Netty is complex though I agree.

Awful/wrong decision is you ask me.

Main focus is on moving off Wildfly (the main use of Undertow) and into Quarkus (which is Vertx/Netty). Makes sense as a business - Netty has a lot more users in the community, e.g. Twitter, Google and Apple. I don't think it's wise for IBM to be re-implementing HTTP3 and many of the other missing features in Java land when it comes to it so consolidating was a good move.

Undertow hasn't had major features properly in a long time. It was almost a solo project and the ex-lead now moved to Quarkus. I really like the API of Undertow!

Probably going to drop support for Netty when Undertow run on top of it.

Would be good to compare once Undertow 3 or 4 comes out to see how much overhead they've added too.

There is a jwt auth module too

Is it a documentation issue? The session store doesn't feel like authentication so maybe I'm misunderstanding it...

Simple caching with annotations and some assistance with API versioning would be good too.

@jknack
Copy link
Member Author

jknack commented Jun 8, 2020

I'm not going to say anything about Quarkus... 😄

Is it a documentation issue? The session store doesn't feel like authentication so maybe I'm misunderstanding it...

Integrates the HTTP Session with JWT token using a cookie or header.

Simple caching with annotations and some assistance with API versioning would be good too.

Yea, this is more or less: module (so we can probably add something today). This thread is more for core changes. Do you have an example of API versioning?

@re-thc
Copy link

re-thc commented Jun 9, 2020

Do you have an example of API versioning?

@Version(1) -- so via annotations on methods / classes and option to set it as either via header, request parameter, or part of the uri to request it. Can return via uri, mime type or header etc.

@inaiat
Copy link

inaiat commented Jun 18, 2020

kotlinx.serialization support!

Would be great to see some native support for https://github.com/Kotlin/kotlinx.serialization

Thanks!

@a1730
Copy link

a1730 commented Aug 25, 2020

Please add a Server API.

This will allow for other server implementations.

Currently we have a choice of Jetty or Netty (Undertow is moving to Netty) with Jooby. However, Netty is very low level and we found their API evolution can be unsettling for production deployments especially when you have multiple Netty based apps with each dependent library asking for different versions of Netty.
There are other good Java based servers see ActiveJ that can host Jooby if there were a Jooby server contract for us to validate our code.

Async Java programming may not be much a gain once project Loom becomes reality. We played with Jetty with Loom (early access) on Jooby - it worked, our code was a joy to read, but we could not certify against a server contract.

@jknack
Copy link
Member Author

jknack commented Aug 25, 2020

The API is: io.jooby.Context, a server implementation must provide a context. It is impossible to require more than io.jooby.Context there are all type of oddities between servers.

@a1730
Copy link

a1730 commented Aug 25, 2020 via email

@jonnii
Copy link

jonnii commented Sep 3, 2020

@jknack assuming this isn't around the corner would it be possible to cut a 2.x release with support for kotlin 1.4?

@jknack
Copy link
Member Author

jknack commented Sep 3, 2020

@jonnii master branch is running on Kotlin 1.4, so next release (2.9.0) comes with it and yea, no work has been done yet on 3.x 👍

@ravihara
Copy link

ravihara commented Sep 12, 2020

This is an open discussion of what we want for Jooby 3.x. For now we will start a discussion here and then cleanup ideas/features to a wiki page (or similar).

Beside is going to be a major release... I'm not planning to break compatibility like we did in 1.x -> 2.x upgrade, so:

* Web site will keep as it is today: https://jooby.io, same goes for Java package: io.jooby.

* The 3.x source code will be just a refactor of existing 2.x source code (not an entire rewrite). Unless something really bad/ugly come up, you will be able to upgrade doing a search/replace session.

Some notes I have so far:

* Review Context API add getter/setter for almost everything (simplify unit test)

* Keep minimum request/response related method into Context (simply context API)

* Add getRequest/getResponse method to Context and add all the necessary getter/setter to each of these new Request/Response API

* Remove bytecode analysis for return types and get back reactive operators (similar to 1.x)

* Remove asm from jooby core

* Kotlin Normal route vs Coroutine route try to simplify usage and remove the HandlerContext object. Favor usage of `fun some(ctx: Context)` and then `get("/route", ::some)`. This probably implies that lambda body route are bind to Context itself

* Rename FileUpload.destroy to close and make it Closable

* Value API make them getter friendly

* Remove runApp. Replace. with new App()

* Rename Jooby class to WebApp?

It could be named as JoobyWeb or just Jooby as it is now.

* Use application.logback.xml so we don't have initialization issues

An overridable logger configuration similar to what log4j2 provides, could be considered too. JSON logging could be helpful these days using logger specific appenders, then.

As always, your feedback is welcome

@jknack
Copy link
Member Author

jknack commented Sep 12, 2020

@ravihara Log4j2 is supported in Jooby 2.x today https://jooby.io/#configuration-logging-log4j2 and you can use log4j.json to configure it.

@ravihara
Copy link

@ravihara Log4j2 is supported in Jooby 2.x today https://jooby.io/#configuration-logging-log4j2 and you can use log4j.json to configure it.

Well! What I was suggesting was, can we have log4j2 as an alternate to slf4j instead of using it via slf4j facade. Something similar to how Vert.x does it. If the plan is to stick to slf4j, I would rather continue to use logback mainly for its native implementation of slf4j api.

@jknack
Copy link
Member Author

jknack commented Sep 12, 2020

Oh got it. will check what vertx does and yes! would like to remove logging from core

@imeszaros
Copy link
Member

Dependency on the Config library could be also dropped to:

  • be more lightweight
  • allow to use the library of choice

Configuration could be done by a DSL like:

{
  configure(cfg -> {
    cfg.serverOptions(so -> {
      so.setPort(90);
      ...
    });
    cfg.application(app -> {
      app.setName("MyApp");
      ...
    });
    // or
    cfg.applicaton(new AppConfig().setName("MyApp"));
  });

  // getting a property
  config().serverOptions().port();
}

And the integration with the Config library could be provided by a module to keep compatibility of course. Users could inject the instances provided by the module to get their own config entries:

{
  require(Config.class).getString("my.entry");
}

@a1730
Copy link

a1730 commented Sep 28, 2020

Time for JPMS review?
We tried to use modules in the past and I believe there were split modules between jooby-core and jooby-test.

@agentgt
Copy link
Contributor

agentgt commented Nov 20, 2020

I agree with @imeszaros on making Config library pluggable.

I have done extensive testing on startup time for our code base and our microservices and the number one thing that really slows startup time for an application before it starts connecting to databases or using massive reflection (e.g. Spring) is resource loading from the classpath.... and I don't mean classes.

For example Log4J2's startup time is 300ms and this is because of the excessive of resource looking up of property files.

Ditto for logback however logback can be loaded using just the service loader (I put that in a long time ago for ceki).

I haven't tested lightbends config time wise for awhile but I know by default it does some resource looking up and I think quite a bit if it can't find config files.

The convenience method ConfigFactory.load() loads the following (first-listed are higher priority):

From lightbend config project page:

system properties
application.conf (all resources on classpath with this name)
application.json (all resources on classpath with this name)
application.properties (all resources on classpath with this name)
reference.conf (all resources on classpath with this name)

Now I think I got around this problem by doing something like:

	public static Environment createEnvironment() {
		ClassLoader cl = Thread.currentThread().getContextClassLoader();
		if (cl == null) {
			cl = JoobyFactory.class.getClassLoader();
		}
		return new Environment(cl, Environment.defaults(), "ignore");
	}

Our microservices jars are like down to 9 Megs and I take great pleasure in every 200 KBs we can shed from them so no hard dependency on Config would be a nice feature in my book .

@agentgt
Copy link
Contributor

agentgt commented Nov 20, 2020

@jknack

Oh got it. will check what vertx does and yes! would like to remove logging from core

On removing SL4J take a look at Min log: https://github.com/EsotericSoftware/minlog

I'm not saying you depend on the library but rather take the code and adapt it for internal logging of Jooby.

Then you make multiple jars for info/debug/warn etc or delagate to SL4J. You can make a production level jar that will true compile time NOOP for INFO and below but fail horrifically on ERROR by dynamically loading SL4J and then logging message and then falling back to System.err (this is how I do it for one of our libraries).

@jknack
Copy link
Member Author

jknack commented Nov 20, 2020

will definitely look at minlog, but yea that is the issue with logging and config: we need to add a new contract/abstraction for each of them... which I don't like it.

@agentgt
Copy link
Contributor

agentgt commented Nov 27, 2020

we need to add a new contract/abstraction for each of them... which I don't like it.

We kind of already have it: Value and Environment.getProperty.

Another alternative is Microprofile Config: https://github.com/eclipse/microprofile-config which is a config facade.

One thing I kind of don't like about Jooby is it tries to do too much initialization and thus is kind of getting into DI boot strapping and wiring space. This is indicative of all the modules that are not strictly related to HTTP.

That is initialization for our Jooby projects:

  1. Config framework
  2. Logging Framework
  3. Possibly Dependency Injection framework but lately we don't use DI
  4. Database layer
  5. Event system layer (kafka, rabbit, etc)
  6. And finally HTTP layer aka Jooby

Jooby seems to want to do:

  1. Logging framework (this because SLF4J static initialization is stupid and requires it to be practically the first thing that gets executed in every java application... thus logback with its XML dialect is the first thing that gets executed)
  2. Jooby
  3. Jooby modules

Because we do the initialization I don't find most of the Jooby modules at all useful especially the database ones.

The problem is the main requirement for sophisticated configuration is because Jooby has a modules system.

I'm not strongly against the module system but that is why the config library seems to need to be complicated. I guess my question is other than the HTTP message encoding modules are folks using the other modules?

See these days I find we don't need complicated configuration libraries nor dependency injection because we no longer make giant monolithic applications but instead do microservices. Thus if there is any config it needs to be flexible in terms of source and available over a network none of which lightbend config offers (our internal config framework does). What isn't really needed is the converting that lightbend config offers... String getProperty(String k) is mostly good enough (IMO).

@agentgt
Copy link
Contributor

agentgt commented Dec 20, 2020

The problem is logging needs to be configured much more than configuration needs logging.

One of the reasons why logback, old log4j, and new log4j2 are overly complex is that they have to provide boot strap configuration options because they have want to be the first to start.

I argue with fairly strong opinion you need boot strap configuration first and if there was a standard for this earlier a lot of complexity could have been removed from the logging libraries.

Even worse because of this config first dependency you often have frameworks boot logging than load the config and the reload all of logging again. This is what dropwizard does (or did) and it’s slow as shit.

@j2eekingcn
Copy link

Before I wrote a project with v1 version, now I upgrade to v2, the code is basically changed. I hope that the api and method of v3 will not undergo major changes. One of the advantages of Java is backward compatibility. I hope Jooby can also Not so radical, in short, I hope jooby gets better and better

@agentgt
Copy link
Contributor

agentgt commented Apr 19, 2021

Some recent thoughts after using jooby in over 10 services I would say more and better MVC annotation support would be appreciated.

The most requested being default/nonnull support for query/form parameters (ie required and a default value).

That is in several MVC/JAXRS annotations APIs you can do something like

@RequestParam(value = "name", default = "someValue", require = true)

I believe Spring MVC supports the above.

Also @QueryParam SomeObject someObject currently will cause the MVC APT code generator to generate byte code that calls ctx.query().convert(...) and not ctx.query("someObject").convert. ctx.query().convert will attempt to use the enitire query string to do conversion. I worked with @jknack on Value converters a while back so I take responsibility on this not being communicated but sometimes you want a single parameter to convert to a Bean (and now Record) vs the entire Query String.

Anyway I think we need a @QueryParams (notice the plural "s") that will always generate byte code for ctx.query() vs ctx.query("nameOfParameter").

@cmitchell
Copy link
Contributor

Any idea when the 3.x version will be released? Or even a 2.9.7 version that includes your recent updates to the gradle plugin? I'm excited to see that you've recently updated jooby to be compatible with a much more recent version of gradle. I would like to be able to take advantage of the joobyRun task, but could continue to just manually execute the jar instead if neitherversion is close to being released.

@jknack jknack unpinned this issue Mar 8, 2022
@jknack jknack pinned this issue Apr 27, 2022
@agentgt
Copy link
Contributor

agentgt commented May 27, 2022

@jknack Just some more thoughts on 3.0.

For 3.0 we might want to checkout EA Loom builds. I believe it will be preview in 19. I think Jetty is the only one that takes advantages of the of new threading model. I am going to experiment running loom with Jooby to see what happens.

3.0 should also just switch to JDK 17 and use the builtin JDK Flow for the reactive stuff.

Consequently 3.0 should be modularized.... however I guarantee that will probably break a few things.

@jknack
Copy link
Member Author

jknack commented May 27, 2022

@agentgt

3.0 should also just switch to JDK 17 and use the builtin JDK Flow for the reactive stuff.

isn't too much? I was planning to go with JDK 11

Consequently 3.0 should be modularized

I'm lost here... Never used them, not sure what to do or were to start. Did you use modules?

@agentgt
Copy link
Contributor

agentgt commented May 28, 2022

isn't too much? I was planning to go with JDK 11

Spring 6 and latest JEE are baselining for Java 17

In my experience there are two groups of users/projects: Java 8 and everyone else. Everyone else can and should run latest greatest. If not the latest LTS which is 17.

The problem with not picking 17 is that other projects will and you might find you will need to do an upgrade sooner than you like (also 11 will be EOL in 4 years).

I'm lost here... Never used them, not sure what to do or were to start. Did you use modules?

Basically module-info.java in packages which I'm sure you know of. Eclipses support of this is better than intellijs but both of them are at odds with Maven.

Anyway if you don't support modules people that do will get annoyed. Spring is even planning on doing it and they have far more problems given the amount of reflection they use.

We are actually planning on biting the bullet and moving to adding module-info.java albeit are reasons for not doing it sooner are different than other peoples (as well as our reasons for doing it).

The reason we haven't done it sooner is because the Maven Shade plugin executable uber jars cannot support modularity (since there can only be one module-info.java). Given docker and docker layers as well as JLink we are considering abandoning this approach as it also seriously slows down build time.

The reasons we want to do it is because I'm a firm believer of compile time separation rules (e.g. database code separated from front end code) aka modularity.

You can do this with Maven but its actually really painful as you either need dummy projects so that you can pull transitive dependencies as <scope>runtime</scope>. That is there is no way in Maven to make a library/module that uses other libraries as <scope>compile</scope> but then say that dependency is <scope>runtime</scope> so that project that depends on the library only sees your library in the classpath. The other way to do this is use/abuse <optional>true</optional>. Or you just put shit in an "internal" package and so don't touch but that still doesn't fix transitive deps.

Let me give you an example. Ideally you can think of Jooby core as two jars/modules. Jooby and Jooby internal (io.jooby.internal). This is because all the stuff in regular Jooby is compile time dep where as internal is runtime and should only be visible to Jooby (io.jooby). However to make to separate jars like that in Maven is nontrivial (e.g. spec and implementation) because of the problems I described earlier.

Why does that matter... well in large particularly monolithic projects developers will use transitive libraries or private implementations when they should not (usually its like commons lang or guava). It also minimize the visible namespace so that you see less stuff when you "ctrl-space" (well Eclipse does... intellij has a tendency to show everything even if the dependency is not added to that module but is in some other project but let's ignore that).

Java Modules fixes the transitive dependency scope as compile problem while also eliminating the need for extra jars or modules just to fix maven scoping issues.

Anyway I can help modularize Jooby. I don't think it will be a lot of work.

@lucaguada
Copy link

Yes, please, I vote for:

  • Java Platform Module System support; it may be easier than trying to adapt Jooby to GraalVM;
  • minimum JDK17 version requirement; with JPMS support, no one will realize what JDK is under the hood.

@imeszaros
Copy link
Member

Anyway I can help modularize Jooby. I don't think it will be a lot of work.

@agentgt If that happens, please involve me somehow. I would like to learn :)

@cmitchell
Copy link
Contributor

I would like to throw in my support for JDK 17

@agentgt
Copy link
Contributor

agentgt commented Sep 11, 2022

@imeszaros @jknack and others I was able to throw a tiny bit of time at modules and it appears undertow is shockingly not a module yet. SLF4J 2.0 luckily is now available and has full module support so at least one core dep is fully compliant. javax.inject is now jakarta which is modularized so that is tedious upgrade of namespace change but very low risk. There probably is even a version of old javax.inject with a different maven coord that is modularized.

I'm surprised by undertow but my guess is the OSS team on Red Hat is more focused on vertx and Quarkus these days. Also undertow I believe has or had plans to switch to netty instead of xnio. It is a shame for us because we use undertow as some of our services use the traditional Servlet spec.

I bring this up because perhaps Jooby 3.0 should target vert.x in lieu of undertow. Perhaps vert.x support should be added to 2.0 to help the migration for those that use undertow like we do. That being said vert.x is really just a wrapper around netty so maybe it isn't even worth it.

@jknack
Copy link
Member Author

jknack commented Sep 11, 2022

fyi @agentgt @imeszaros I started to work on 3.x. The main branch is now 3.x

I don't like the idea to run on top of adding vert.x and 2.x no more big changes there.

@agentgt
Copy link
Contributor

agentgt commented Sep 12, 2022

I agree. I just floated the vertx option if folks wanted to have a single underlying HTTP server/servlet implementation throughout their code base but as I said it really adds very little value to jooby as vertx itself is built on netty and jooby already is. If undertow switches to Netty then undertow is basically like vertx and doesn't add much value.

I guess the point I'm making is I would consider Undertow in jooby 3.0 lower priority given its apparent future and possibly replaced. Loom may change a lot of stuff so something like Helidon Nima maybe a better 3rd option to explore.

@jknack jknack removed this from the 3.0.0.M1 milestone Dec 5, 2022
@jknack
Copy link
Member Author

jknack commented Dec 5, 2022

First milestone is out: https://github.com/jooby-project/jooby/releases/tag/v3.0.0.M1

Still lot more to do.

@agentgt
Copy link
Contributor

agentgt commented Jan 13, 2023

@jknack is there a possible chance we can add automatic modules in the META-INF/MANIFEST.MF for v2.x?

The reason being is it will make it easier for me to test 3.x on our code base by swapping them out (I know there are api changes but I can deal with that) while still retaining a module-info in our projects.

@jknack
Copy link
Member Author

jknack commented Jan 13, 2023

I don't have time to do it but also isn't a good idea. I don't want to get bugs, questions on 2.x around modules.

@agentgt
Copy link
Contributor

agentgt commented Jan 13, 2023

Yeah I was thinking the same while driving that I will just upgrade v3 across the board that way I can better help you as it will get confusing for me if we have issues.

Plus I assume v3 will get updates faster anyway and you generally accept PRs from me so I'll go ahead with it.

@jknack
Copy link
Member Author

jknack commented Jan 13, 2023

Right. 2.x will go to maintenance mode, no more (new) changes there.

@Blquinn
Copy link
Contributor

Blquinn commented Jan 24, 2023

@agentgt @jknack I played around with enabling virtual threads on Jetty as well as a super bare bones Helidon Nima server implementation for Jooby. Let me know what you think. I know this isn't exactly related to the release, but I saw you all talking about loom up above. Maybe we can enable the Jetty virtual thread options if you're on Java 19 somehow?

Jetty Loom Branch

Helidon Nima Server Branch

@agentgt
Copy link
Contributor

agentgt commented Jan 24, 2023

@Blquinn The best way to do it would be manual wiring or through the ServiceLoader with some caveats.

I can't remember how we load up the various Server implementations but if it is with the ServiceLoader which I'm fairly sure it is (it is) then sadly you would not be able to decorate the existing Jetty Server implementation. This is actually a problem with most SLF4J implementations as well (ie there is no way to decorate say logback with your own slf4j implementation).

https://github.com/jooby-project/jooby/blob/3.x/modules/jooby-jetty/src/main/java/module-info.java#L22

There is actually a pattern I follow because of this but I'm fairly sure @jknack is not going to like this.

Basically you make an abstract jar that has almost the entire implementation minus the ServiceLoader registration.

Below is how the modules would look (modules being jpms jars).

jooq-jetty <-- all jetty code
jooq-jetty-server-plugin <-- ServiceLoader maybe using static provides method
jooq-jetty-server-loom <-- depends on jooq-jetty and wraps it for loom and compiled 19
jooq-jetty-server-loom-plugin <-- depends on jooq-jetty-server-loom and has ServiceLoader registration

Of course the easiest thing for now is to literally copy all the code in the io.jooby.jetty module.

BTW most folks do not know that you no longer need a no-arg class anymore to create for the ServiceLoader and instead can create static method like:

public class LoomJetty {
    // the method has to be static, public and named provides
    public static Server provides() {
      // create jetty server code using shared logic or copied logic
    }
}

And thus you avoid the constructor annoyances and or having to use the delegate pattern.

@agentgt
Copy link
Contributor

agentgt commented Jan 24, 2023

@Blquinn

I guess what I'm saying is the easiest thing to do for now is to make separate projects for nima and jetty that are outside of jooby. Use the ServiceLoader registration to make your own Servers. You will have to duplicate jetty logic for now.

That way you avoid jooby code base locked on 17 (albeit there are ways to compile with multiple jdks in maven it isn't worth it).

Then the instructions are simple. Tell whoever to include your module (maven runtime dep) instead of jooby-jetty.

@Blquinn
Copy link
Contributor

Blquinn commented Jan 27, 2023

@agentgt Yea I did suspect that copying everything would probably be the easiest way. Thanks for the info though. I'm somewhat familiar with ServiceLoader because I had to use it already for nima to work.

I guess I'm wondering if it's worth setting up a separate module, I'm not really sure if anyone will be interested in using this, or not. Jetty at least is basically ready to go because its just a couple lines of code, maybe that would be worth it.

@agentgt
Copy link
Contributor

agentgt commented Jan 27, 2023

'm not really sure if anyone will be interested in using this, or not. Jetty at least is basically ready to go because its just a couple lines of code, maybe that would be worth it.

I'm sure they will assuming the quality is good (btw you might want to remove what I assume is an accidental kotlin dep). In fact I would be curious to see it in the techempower results. Hell I was going to do what you are already doing myself I just didn't have the time. So sally forth with testing loom 👍

@Blquinn
Copy link
Contributor

Blquinn commented Jan 28, 2023

@agentgt Okay, you've convinced me ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests