katharsis-project / katharsis-framework

Katharsis adds powerful layer for RESTful endpoints providing implementenation of JSON:API standard
http://katharsis.io
Apache License 2.0
135 stars 65 forks source link

RepositoryNotFoundException from buildPath #432

Open phuo1032 opened 7 years ago

phuo1032 commented 7 years ago

Hi, I am using springboot and encountered the following error when I use the webprefix: "api" and resource type "todos"

io.katharsis.errorhandling.exception.RepositoryNotFoundException: Repository for a resource not found: /api/todos/

I was doing some debugging, the exception seems to be thrown because ResourceRegistry tries to get resource by the path name api or api/todos, where the only available resource type is "todos".

I was comparing the springboot example and put a break point at this place

https://github.com/katharsis-project/katharsis-framework/blob/master/katharsis-spring/src/main/java/io/katharsis/spring/KatharsisFilterV2.java ->

`private String getRequestPath(HttpServletRequest request) {
    String path = request.getPathInfo();

    // Serving with Filter, pathInfo can be null.
    if (path == null) {
        path = request.getRequestURI()
                .substring(request.getContextPath().length() + webPathPrefix.length());
    }

    return path;
}`

At the first line, my path returns "api/todos" so it skips the null case. But in sprintboot example, the path from first line is null. After the null case it returns "tasks". They don't seem to be equivalent to each other. But trying to find the resource with webprefix as part of the path seems to be incorrect.

chb0github commented 7 years ago

Thanks for all the debug. I will try to have a peek tomorrow

On Thu, Jun 1, 2017, 12:26 PM phuo1032 notifications@github.com wrote:

Hi, I am using springboot and encountered the following error when I use the webprefix: "api" and resource type "todos"

io.katharsis.errorhandling.exception.RepositoryNotFoundException: Repository for a resource not found: /api/todos/

I was doing some debugging, the exception seems to be thrown because ResourceRegistry tries to get resource by the path name api or api/todos, where the only available resource type is "todos".

I was comparing the springboot example and put a break point at this place

https://github.com/katharsis-project/katharsis-framework/blob/master/katharsis-spring/src/main/java/io/katharsis/spring/KatharsisFilterV2.java ->

` private String getRequestPath(HttpServletRequest request) { String path = request.getPathInfo();

// Serving with Filter, pathInfo can be null.
if (path == null) {
    path = request.getRequestURI()
            .substring(request.getContextPath().length() + webPathPrefix.length());
}

return path;

}`

At the first line, my path returns "api/todos" so it skips the null case. But in sprintboot example, the path from first line is null. After the null case it returns "tasks". They don't seem to be equivalent to each other. But trying to find the resource with webprefix as part of the path seems to be incorrect.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/katharsis-project/katharsis-framework/issues/432, or mute the thread https://github.com/notifications/unsubscribe-auth/ABaI0O7fWa80FDqjGXdel3POJUHxXA1hks5r_xB0gaJpZM4Ntbra .

dexstakker commented 7 years ago

I would be very interested in this answer also.

chb0github commented 7 years ago

I am looking at our spring-boot example right now - I have tasks and projects and both respond correctly.

I need some reproducible code. If you wanna submit a PR I can have a look or you can give me some snippets

phuo1032 commented 7 years ago

Yes, spring-boot example is returning response correctly because in the first line of the following function, request.getPathInfo() returns null. So the final return value is actually constructed manually.

private String getRequestPath(HttpServletRequest request) {
    String path = request.getPathInfo();

    // Serving with Filter, pathInfo can be null.
    if (path == null) {
        path = request.getRequestURI()
                .substring(request.getContextPath().length() + webPathPrefix.length());
    }

    return path;
}

In our app, request.getPathInfo returns "api/tasks", which would not be the right path that can locate the resource. If it also returns null, the manual construction would also returns "tasks".

I suppose the idea of this function is if it doesn't get the PathInfo from the request, it constructs it with requestUri - (contextPath + prefix). But that's assuming contextPath + prefix = the servlet path, which is not always the case. We would fix this by removing the first line (i.e just construct it manually), but we cannot be sure it will not break any other use cases. Therefore, we are interested if there is a different way to resolve this.

dexstakker commented 7 years ago

In other words, is there a case where getPathInfo() returns a non-null value that is part of an example that runs correctly? Because it IS causing other cases to NOT run correctly.

hibaymj commented 7 years ago

Can you show how you are setting this prefix, or better yet send a PR with a minimum configuration to replicate the issue?

phuo1032 commented 7 years ago

The only configuration we have is adding the following to application.properties

katharsis.resourcePackage=[domainPackage] katharsis.domainName=http://localhost:8080 katharsis.pathPrefix=/api

A model with @JsonApiResource(type = "todos"): Todo.java A repository with Todo as the resource: TodoRepositoryImpl

Note that if I use @JsonApiResource(type = "api/todos") in Todo.java, we got around this issue. Everything is working except the type is shown as "api/todos" and self.link is "localhost:8080/api/api/todos". They are expected because we purpose add api/ to the resource type.

phuo1032 commented 7 years ago

Forgot to mention that we also added

@Configuration @Import({ KatharsisConfigV3.class })

to Application.java