Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Spark The requested route [/users/] has not been mapped in Spark for Accept: [*/*]

Tags:

java

put

I have the following method to modify a user in my Postgres database:

public void modifyUser(User usr){
    try (Connection conn = sql2o.beginTransaction()){
        conn.createQuery("update public.\"user\" set name=:name, lastname=:lastname, email=:email where id=:id")
                .addParameter("id", usr.getId())
                .addParameter("name", usr.getName())
                .addParameter("lastname", usr.getLastname())
                .addParameter("email", usr.getEmail())
                .executeUpdate();
        conn.commit();
    }
}

that is called by this method:

//update
    put("/users", (request, response) -> {
        response.type("application/json");
        User user = new Gson().fromJson(request.body(), User.class);
        model.modifyUser(user);
        return new Gson().toJson(response);
    });

I use Postman to specify the body, this way:

{   "id": 3, 
"name": "Mary",
"lastname": "Changed",
"email": "email"
}

But, even if the post method is working fine, this "put" operation throws the following error:

spark.http.matching.MatcherFilter - The requested route [/users/] has not been mapped in Spark for Accept: [*/*]

I don't get what the error is. I couldn't find ny solution.

like image 435
Usr Avatar asked Oct 29 '25 11:10

Usr


2 Answers

I know this is an old thread but I was hoping to provide some extra info on the topic.

The path's "/users" and "/users/" are 2 different paths, thus optionally allowing 2 different spark routes (spark's actually really well made like that, in my opinion).

Below is an example of how I typically address this [pun intended, not sorry] in my spark servers when I do NOT want 2 different routes for these:

path("/user", () ->
{
    get("", GenericRoutes.redirectToSlashIndex);
    get("/index.html", GenericRoutes.pathGet_index);
    get("/*", GenericRoutes.redirectToIndex);
});

The idea here is that the first ("") sends to the second ("/index.html") and the third ("/*") sends any non-existing paths to the second ("/index.html") as well.

Then in Generic Routes class you'd have something like:

public static final Route redirectToIndex = new Route()
        {
            @Override
            public Object handle(Request request, Response response) throws Exception
            {
                String path = request.pathInfo();
                path = path.substring(0, path.lastIndexOf('/')+1)+"index.html";
                response.redirect(path, 301);
                return "<html>Redirecting...</html>";
            }
        };

public static final Route redirectToSlashIndex = new Route()
        {
            @Override
            public Object handle(Request request, Response response) throws Exception
            {
                response.redirect(request.pathInfo() + "/index.html", 301);
                return "<html>Redirecting...</html>";
            }
        };

I've simplified some of what I usually do here (you may want some more error handling in those routes and auth checks via 'before' outside of those routes). However here is a small sample of how this works:

  • Nav: "/users" -> calls get("",...) -> redirects to: "/users/index.html"
  • Nav: "/users/" -> calls get("/*",...) -> redirects to: "/users/index.html"
  • Nav: "/users/index.html" -> calls get("/index.html",...) -> no redirects.

So you can see how using something like this will allow you to send the traffic to where you'd expect. There's some things to keep in mind, however:

  1. Using this can be problematic when you have URL params/tokens (you may lose them if you're not careful)
  2. the order is important because if "/*" was before "/index.html" then "/users/index.html" would always trigger "/*" (and infinitely redirect) instead of triggering the route for "/index.html"
  3. In my example I'm using get, thus this approach is typically what is intended (save #1), however with others (such as put/post for example) changing the path like this can result in unexpected outcomes, so be careful when using this approach that you don't redirect traffic to unintended endpoints.
  4. If SEO is important to you, you may consider using this method I've described above as a 301 to hint to those that are crawling your site that your output URL is a permanent redirect. This may be preferable to just putting the same route for all endpoints (which is also a valid alternative [see below]).

Mine is intentionally a bit more complicated than yours, here's how you could handle yours:

path("/user", () ->
{
    /*Looks like you mentioned you had a post with the 'first version', so I think like this?*/
    post("", UserRoutes.postUsers); //post: /users
    put("", UserRoutes.putUsers); //put: /users
    put("/*", UserRoutes.putUsers); //put: /users/
});

Note that in the last put example above you could do "/*" or just "/". With * you'll catch any path starting "/users/" whereas without * you only allow "/users/" through. So with * you could do "/users/e13a319e-16d9-3ff5-a83c-96564007998e" and it would trigger the endpoint but that same path would fail without *, this directly relates to #1 above.

So which method you go with really depends on the intent of your site and what you do or do not want those hitting your endpoints to do & see. Happy coding!

like image 194
NekoKikoushi Avatar answered Oct 31 '25 01:10

NekoKikoushi


Don't know the exact reason why, but the problem was in

put("/users", (request, response) -> {

Spark wants it, in this case, to be written as

put("/users/", (request, response) -> {

Differently from "post" method that accept the first version.

like image 34
Usr Avatar answered Oct 31 '25 00:10

Usr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!