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

Javalin 3.0 suggestions and feature request #514

Closed
19 tasks done
tipsy opened this issue Mar 23, 2019 · 37 comments
Closed
19 tasks done

Javalin 3.0 suggestions and feature request #514

tipsy opened this issue Mar 23, 2019 · 37 comments

Comments

@tipsy
Copy link
Member

tipsy commented Mar 23, 2019

Feel free to discuss Javalin 3.0 in this issue.

Please create new issues if you have specific requests.

The current milestone (roadmap) can be seen here: https://github.com/tipsy/javalin/milestone/7

Current changelog: dbf2090...HEAD

Javalin 2.8.X will receive security updates when 3.0 is out, but no new features.

Alpha/beta builds available at: https://javalin.io/future/documentation

Progress

Misc

  • Rewrite configuration setup
  • Remove old validation methods and simplify Validator classes
  • Make routing case sensitive
  • Let FileRenderer throw exception
  • Add config option: asyncRequestTimeout
  • Add config option: enforceSsl
  • Rework event system
  • Rework package structure
  • Consider publishing a javalin-servlet separately (rejected)
  • Expose JavalinServlet in a better way
  • OpenAPI/Swagger support

WebSocket

  • Simplify WebSocket API (make all websockets take a WsContext)
  • Add WebSocket AccessManager
  • Add to/from JSON to WebSocket methods
  • Human-readable method names for WebSocket interfaces
  • Add cookies to WsContext
  • Add attributes to WsContext
  • Sync WsContext and Context APIs (use Context proxy)
  • Add wsBefore/wsAfter and wsException
@kran
Copy link

kran commented Mar 27, 2019

maybe formParamMap is good to support nested form data.

@ghost
Copy link

ghost commented Mar 27, 2019

Rewriting to be based on Java 8 instead of Kotlin, but still be Kotlin-viable.
Under certain circumstances, pulling 5 kotlin related libs, including sdk might not be acceptable.
I remember there was discussion about it some time ago and I could see couple valid points there.

Java is the language (IMO) that lacks good framework like Javalin, in Kotlin, there are alternatives.
I think (I'm not sure though) that majority of users actually come from Java, and Kotlin users wouldn't probably even notice it, so ...

@tipsy
Copy link
Member Author

tipsy commented Mar 27, 2019

@kran What is nested form data?

@majorpasza There are mostly upsides to rewriting to Java, except for one thing... It has to be written in Java. I didn't think that was so bad until I actually started rewriting it. I've become very accustomed to Kotlin over the years, and going back to Java was kind of a shock. The majority of users use Kotlin (although it's very close to 50/50), but that's not really an argument. As you say, they wouldn't really notice. Javalin is almost two years old now, and no one has complained about the Kotlin dependencies yet, so it doesn't appear to be a problem. It's probably mainly something which bothers me and other people working on the project. All things considered, I think it's better to spend time on new features and API improvements, compared to a Java rewrite.

@kran
Copy link

kran commented Mar 28, 2019

@tipsy
form field's name likes: fld[] or fld[name], they should be mapped into array or map, and the key should be just "fld", but not "fld[]" or "fld[name]".

@fuuqiu
Copy link

fuuqiu commented Mar 28, 2019

data class student(var name:String = "kangkang", var age : Date? = null)

//request json: {"name":"jan","date":"1553741222"} ps: date is CST Unix timestamp   CST:2019-03-28 10:47:02
val student = Context.bodyAsClass(Student::class.java) 
println(student.age)  //1970-1-1 00:00.000 Date  GMT = CST + 8   why?

Can the new version be just a different time zone? Thank you very much for your help.

@inaiat
Copy link

inaiat commented Mar 28, 2019

Hello @tipsy! Great work that you have done! After I use Spark in some projects I would enjoy to use Javalin. I have some issues to use Javalin in Google App Engine. I will appreciate a lot that you implement something like SparkFilter. Thank you.

@tipsy
Copy link
Member Author

tipsy commented Mar 28, 2019

@kran can you show me in code?

@fuuqiu This is not really related to Javalin, it's Jackson. You can configure your own Jackson mapper by calling JavalinJackson.configure(...)

@inaiat thank you! I'm not sure what "something like SparkFilter would mean in this sense", but it's possible to do this:

@WebServlet(urlPatterns = ["/rest/*"], name = "MyServlet")
class MyServlet : HttpServlet() {
    val javalin = EmbeddedJavalin()
        .get("/rest") { ctx -> ctx.result("Hello!") }
        .createServlet()

    override fun service(req: HttpServletRequest, resp: HttpServletResponse) {
        javalin.service(req, resp)
    }
}

Javalin 3 will make the process of creating a JavalinServlet easier than it currently is.

@inaiat
Copy link

inaiat commented Mar 28, 2019

@tipsy In my apps with sparkjava I use in this way:

@WebFilter(
        filterName = "InitFilter", urlPatterns = {"/*"},
        initParams = {
                @WebInitParam(name = "applicationClass", value = "AppFilter")
        })

public class AppFilter extends spark.servlet.SparkFilter {
}

SparkFilter implements javax.servlet.Filter. The implementation of SparkFilter is here: https://github.com/perwendel/spark/blob/master/src/main/java/spark/servlet/SparkFilter.java

Thanks.

@fuuqiu
Copy link

fuuqiu commented Mar 29, 2019

@tipsy Thank you very much, I am negligent, I found the relevant configuration of jackson in the configuration, and now it has been modified. If you can add some data class data verification in version 3.0, I think this will be a very good function.

@kran
Copy link

kran commented Mar 29, 2019

sorry for my weak english.

here is the code.

form:

<form method="post" action="/form">
    <input type="checkbox" name="sel[]" value="x"/>
    <input type="checkbox" name="sel[]" value="y"/>
    <input type="text" name="user[age]" />
    <input type="text" name="user[name]"/>
    <input type="submit">
</form>

handler:

        app.post("/form", ctx -> {
            Iterator<Map.Entry<String, List<String>>> iter = ctx.formParamMap().entrySet().iterator();
            iter.forEachRemaining(it -> {
                System.out.printf("%s => %s\n", it.getKey(), it.getValue().toString());
            });
        });

output:

sel%5B%5D => [x, y]
user%5Bage%5D => [dfdf]
user%5Bname%5D => [1]

keys are encoded and include [].

in other languages/frameworks, like PHP, the struct is like this:

array(2) {
  ["sel"]=>array(2) {
    [0]=>string(1) "x"
    [1]=>string(1) "y"
  }
  ["user"]=>array(2) {
    ["age"]=>string(2) "11"
    ["name"]=>string(2) "22"
  }
}

@asad-awadia
Copy link

@tipsy Support for kotlin coroutines please

Being able to launch coroutines and let them do things async-ly and independent of the req/resp flow would be great

@tipsy
Copy link
Member Author

tipsy commented Apr 9, 2019

@asad-awadia currently you can do ctx.result(myFuture), why would coroutines be an improvement?

Edit: There's this for converting a coroutine to a future: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-jdk8/kotlinx.coroutines.future/kotlinx.coroutines.-coroutine-scope/future.html

@asad-awadia
Copy link

@tipsy

  • Future's are unintuitive/clunky to work with
  • They add an unneeded layer of async
  • Coroutines is hands down one of the most nice/loved/innovative features in kotlin so support for that would help
  • Coroutines also allow being able to spin off things outside the request/resp flow - I don't necessarily need to send it as the response but kicking off a coroutine which delays(some-time) and then triggers a socket send to the client is extremely handy
  • Coroutines also allow for rest requests to register into 'pipelines' where data is communicated via channels and go through multiple coroutines as processing steps and then get sent back or updated in DB/redis etc

@tipsy
Copy link
Member Author

tipsy commented Apr 11, 2019

I'm not saying coroutines aren't nice, but you don't really have to deal with async at all in Javalin (at least that's the idea). You should be able to write all your code with coroutines if you do somthing like ctx.result(futurify{coroutine})? Then Javalin will take care of the future part.

Interoperability and "sameness" are key concerns for Javalin, so I don't want to introduce a concept that will only benefit Kotlin users.

@tipsy tipsy removed the JAVALIN 3.0 label Apr 12, 2019
@jehugaleahsa
Copy link

Let me start by saying I love this project. Of all the options available for Java, Javalin is light-weight and easy to work with. I was able to write a simple MVC framework (similar to ASP.NET Core) that uses annotation processing to build Javalin route definitions at compile time. Javalin makes a great core to my web stack.

One of things I found myself doing was using a 404 handler to support my single-page applications. I have to be careful because I am using enableStaticFiles. If a route doesn't match, I need to make sure it looks for a static file first and then fallback on my SPA. The challenge there is I need to ignore 404's returned by my REST API and non-GET requests. A short-hand for this would be useful...

A short-hand for top-level error handling would be nice, too. Right now, I just write this:

app.exception(Exception.class, (e, ctx) -> {
    logger.error("Encountered an unhandled exception.", e);
    ctx.status(500);
});

Again, that works, but I could see most users not wanting to deal with that. A simple app.unhandledException((e, ctx) -> ...) would be nice. It's more explicit.

Honestly, I love how small this project is. I'd hate to see it get weighed down with features I'd never use. There's plenty of room for little conveniences, though. I feel like there was something else I had on my wish list. If I remember it, I will be sure to share. Thanks!

@tipsy
Copy link
Member Author

tipsy commented Apr 15, 2019

@jehugaleahsa thank you very much! There is a single page handler already:

app.enableSinglePageMode("path", "filePath") // catch 404s and return file-content as response body

I think it does exactly what you want (?).

For your second point, I'm not sure you save that much?

app.exception(Exception.class, (e, ctx) -> {});
app.unhandledException((e, ctx) -> {});

Why do you think this is better? One of my main goals for 3.0 is to slim down the number of methods on the Javalin class, so I don't think I'll add this one.

@Nezteb
Copy link

Nezteb commented Apr 17, 2019

OpenAPI/Swagger spec generation (#254), similar to HTTP4K and SpringFox.

Neither Javalin, Ktor, nor SparkJava support it. Ktor offers codegen (Swagger -> Code), but not the other way around (Code -> Swagger).

In my opinion, codegen isn't nearly as useful as spec generation.

@scorsi
Copy link

scorsi commented Apr 18, 2019

Hello,
Is it possible to see code helpers or docs to build micro-services architecture using Javalin ? :)

@kindywu
Copy link

kindywu commented Apr 19, 2019

javalin how to integrated with jpa,redis ,i try to use it for some small system

@tipsy
Copy link
Member Author

tipsy commented Apr 19, 2019

@Nezteb Swagger support would be great, but I don't have any good ideas for how to solve it. If you want to try I'd be happy to help.

@scorsi Could you be a bit more specific? Are you talking about infrastructure, project structure, or something else?

@kindywu What do you mean support? You can use both of them fine, what would the support include?

@scorsi
Copy link

scorsi commented Apr 19, 2019

@scorsi Could you be a bit more specific? Are you talking about infrastructure, project structure, or something else?

Hey @tipsy,
I'm talking about infrastructure and some code inside Javalin to handle micro-services, something like:

import io.javalin.Context
import io.javalin.Javalin
import io.javalin.apibuilder.ApiBuilder
import io.javalin.apibuilder.ApiBuilder.get

// JAVALIN INTERNAL CODE

interface Microservice {
    fun route()
}

fun Javalin.microservice(path: String, microservice: MyMicroservice) {
    routes {
        ApiBuilder.path(path) { microservice.route() }
    }
}

// END OF JAVALIN INTERNAL CODE

object MyMicroservice : Microservice {
    override fun route() {
        get("/toto", this::getToto)
    }

    private fun getToto(ctx: Context) {
        ctx.result("Hello World")
    }
}

fun main() {
    val app = Javalin.create().start(7000)
    app.microservice("/my-microservice", MyMicroservice)
}

The goal is to have a micro service per jar file (Gradle/Maven project) and to easily implement them like the app function. It should delegate more easily the code.
I don't know if that code is working with different Gradle project since it uses the io.javalin.apibuilder.ApiBuilder.staticJavalin instance.
That code may be bad.

EDIT:
Or may be to explain how to do micro-services with multiple Javalin application in a tutorial ? ;)

@tipsy tipsy removed this from the Javalin 3.0.0 milestone Apr 20, 2019
@vrozkovec
Copy link

Hi, what about implementing JSR 380 Bean validation 2.0?

Then we could use some of these goodies:

@NotNull – validates that the annotated property value is not null
@AssertTrue – validates that the annotated property value is true
@Size – validates that the annotated property value has a size between the attributes min and max; can be applied to String, Collection, Map, and array properties
@Min – validates that the annotated property has a value no smaller than the value attribute
@Max – validates that the annotated property has a value no larger than the value attribute
@Email – validates that the annotated property is a valid email address

And this would not have to be necessary:

// validate a json body:
MyObject myObject = ctx.bodyValidator(MyObject.class)
        .check(obj -> obj.val > 0 && obj.val < 5)
        .getOrThrow();

But I may be missing something and perhaps it is easy to plug my own validation already.

Some links:
[1] https://beanvalidation.org/2.0/
[2] https://www.baeldung.com/javax-validation

@tipsy
Copy link
Member Author

tipsy commented Apr 21, 2019

@vrozkovec I'm fine with that, but it would have to be an optional dependency. Would you like to submit a PR?

@scorsi I'm having some trouble understanding. You want to create one Javalin-instance per endpoint?

@vrozkovec
Copy link

@tipsy when should be PR ready to make it to 3.0?

@tipsy
Copy link
Member Author

tipsy commented Apr 21, 2019

@vrozkovec The preliminary completion date is set to June, so some time before that. I will be releasing alpha/beta builds though, the first alpha version was released today.

@ivanquirino
Copy link

I would like for an easy and simple way to deploy javalin on serverless environments (aws, google...)

@asad-awadia
Copy link

Protobuf over rest?

@tipsy
Copy link
Member Author

tipsy commented Apr 25, 2019

@asad-awadia have a look at this issue: #453

What support is required?

@asad-awadia
Copy link

@tipsy nvm then lol

@vinigmoraes
Copy link

vinigmoraes commented May 3, 2019

Hi, is it possible to add a way to throw my own exception when validating request body instead use getOrThrow in check?

ctx.bodyValidator(MyObject.class)
        .check(obj -> obj.val > 0 && obj.val < 5)
        .getOrThrow();

@tipsy
Copy link
Member Author

tipsy commented May 3, 2019

@vinigmoraes The API for this has changed a bit with 3.0, the last call is just called get() now. If you'd like, you could add a getOrThrow which takes an exception ?

@mikoet
Copy link

mikoet commented May 6, 2019

Would it be possible to make the size of thread-pool (min, max) configurable for the integrated Jetty?

I'd like to use Javalin with Hibernate, but with the default thread-pool size of up to 250, I'm not sure if I want to possibly have 250 Hibernate sessions. Or does this sound stupid?

@tipsy
Copy link
Member Author

tipsy commented May 6, 2019

You can already run on a custom server by calling app.server() @mikoet.

@tipsy
Copy link
Member Author

tipsy commented May 16, 2019

@TobiasWalle If you're okay with it, I'd like to mention you by name in the OpenAPI section of the 3.0 release announcement. Do you have any profile you'd like me to link to (LinkedIn, GitHub, Twitter?). Or would you prefer to stay anonymous?

@tobias-walle
Copy link
Contributor

tobias-walle commented May 16, 2019

@tipsy Thank you! You can link my GitHub and LinkedIn. I'm looking forward for the announcement and the release!

@fuuqiu
Copy link

fuuqiu commented May 16, 2019

Is the 3.0 version going to be updated? It’s a good news. Looking forward to the release.Is there a related Telegram group for javalin?

@tipsy
Copy link
Member Author

tipsy commented Jun 6, 2019

Getting close to release, so closing this issue.

@tipsy tipsy closed this as completed Jun 6, 2019
@tipsy tipsy unpinned this issue Jun 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests