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

ResourceHandler does not provide defaultLogger #4

Closed
flaxel opened this issue Oct 22, 2020 · 19 comments
Closed

ResourceHandler does not provide defaultLogger #4

flaxel opened this issue Oct 22, 2020 · 19 comments
Assignees

Comments

@flaxel
Copy link

flaxel commented Oct 22, 2020

It's possible that extending ResourceHandler is improperly generated because that is only supported by "configuration resources" (declared in vlingo-http.properties). For dynamic resources handlers the Stage must be passed in via constructor. With the Stage the dynamic resources handlers can get to anything needed, including the Logger.

/cc @danilo-ambrosio @Florian-Schoenherr

@Florian-Schoenherr
Copy link
Contributor

Florian-Schoenherr commented Oct 22, 2020

Could you use this for now?

private final Stage stage;
private final Logger logger;
public SomeResource(final Stage stage) {
       this.stage = stage;
       this.logger = stage.world().defaultLogger();
}

If you want to generate more Resources right now, I could change the generation to include these lines. If you just need it on one or two, or on already generated Resources, you can copy it in.
Sorry, I really thought the logger() from ResourceHandler was usable like that!
I will keep this open until this is resolved in a better way.
This will suffice for now.

@flaxel
Copy link
Author

flaxel commented Oct 22, 2020

Oh yeah, that's okay. 👍 Thank you for your fast support! 😄

@VaughnVernon
Copy link
Contributor

@Florian-Schoenherr Has the code generation been fixed such that it supports your suggestion?

#4 (comment)

@Florian-Schoenherr
Copy link
Contributor

Florian-Schoenherr commented Oct 28, 2020

@VaughnVernon I kept this open mainly because #5 was not the most optimal solution. We could close, but I think there is still some misconception of extends ResourceHandler:
In http docs:
http
In xoom docs:
xoom
And as said in #5, ServerActor doesn't know about routes without extends ResourceHandler, which means ResourceHandler is either used wrong or should have a stage (&context).

The fix I applied is just "here, have another logger".

@VaughnVernon
Copy link
Contributor

Thanks, @Florian-Schoenherr

@danilo-ambrosio When you have an chance, please address this. I don't know where the problem is:

  • Does the @ResourceHandler annotation require extends ResourceHandler? If so, that is incorrect. When routes() is used the resource handler class is freed from the use of extends ResourceHandler because it is now a DynamicResourceHandler rather than a ConfigurationResourceHandler (created by using the definition in the vlingo-http.properties).

  • Is the Starter code generation generating the extends ResourceHandler? I think in either case, using annotations or not, this would be incorrect. My understanding is both when using annotations and not, the resource handler is always configured via routes() and thus extend ResourceHandler would never be appropriate.

The problem is that when extends ResourceHandler is used with a DynamicResourceHandler it will never be initialized for each request that is handled, and thus, trying to access the inherited members will cause NullPointerExceptions.

@Florian-Schoenherr
Copy link
Contributor

I tried removing extends ResourceHandler in schemata, e.g. right here, which doesn't work. That's the only thing I really know.
(also, routes does Override ResourceHandler::routes())

@VaughnVernon
Copy link
Contributor

VaughnVernon commented Oct 29, 2020

If you remove extends ResourceHandler then routes() is no longer an @Override. In other words, just remove the @Override and you should be good to go. I don't understand why this would be a problem otherwise.

@Florian-Schoenherr
Copy link
Contributor

That did not work. Maybe it was something specific to schemata, my guess is that xoom's
@ResourceHandlers(packages = "io.vlingo.schemata.resource") looks at everything inside io.vlingo.schemata.resource that extends ResourceHandler.
@danilo-ambrosio is that correct?

@danilo-ambrosio
Copy link
Contributor

You're right, @Florian-Schoenherr.

ResourceHandler is also used as a key, speeding up the search for valid Resource classes inside a given package. I wasn't aware of the impacts @VaughnVernon mentioned when you extend ResourceHandler, but I have a straightforward solution. I can simply create a markup abstract class on vlingo-xoom for that purpose. Thus, we can maintain the package attribute of @ResourceHandlers annotation, which ease the resource handlers mapping.

What do you think? @VaughnVernon @Florian-Schoenherr

@VaughnVernon
Copy link
Contributor

VaughnVernon commented Oct 30, 2020

@danilo-ambrosio Do you mean a marker class/interface? I prefer not to use one. However, you could put a meaningful method on the interface:

public interface DynamicResourceHandler {
  Resource<?> routes();
}

Now overriding Resource<?> routes() in the implementing class makes sense.

@Florian-Schoenherr
Copy link
Contributor

Well, I know why marker-classes are not so nice. Also, aren't annotations supposed to be used for marking (too)?
Then again, having annotations on every resource class is also not what we are going for.

The interface with routes() from @VaughnVernon makes sense, maybe we could make it an abstract class and provide the logger(), too. Although having thought about it, generating the logger like this.$logger = $stage.world().defaultLogger(); makes more sense, because beginners will then have it right there and you can still just delete it if you didn't need it.
So we just want routes().

@danilo-ambrosio do we need anything else on the marker class/interface?

@VaughnVernon
Copy link
Contributor

@Florian-Schoenherr @danilo-ambrosio It could be an abstract base that has a constructor that requires the Stage and holds that and the logger. That's fine. I don't think it matters much in terms of code gen.

public abstract class DynamicResourceHandler {
  private final Logger logger;
  private final Stage stage;

  public abstract Resource<?> routes();

  protected DynamicResourceHandler(final Stage stage) {
    this.stage = stage;
    this.logger = stage.world().defaultLogger();
  }

  protected Logger logger() {
    return logger;
  }

  protected Stage stage() {
    return stage;
  }
}

@danilo-ambrosio
Copy link
Contributor

danilo-ambrosio commented Oct 30, 2020

@Florian-Schoenherr

We could use annotations but we still need to ensure some methods implementation on resources classes.

If we use annotations instead of marker interface/class, then a compile-time validation is required for making sure the right methods are implemented. That takes time to be implemented.

So I vote for @VaughnVernon 's suggestion which seems to be simpler. Note that Stage needs to be "injected" because, when using xoom annotation, developers are not able to do it by editing the Bootstrap class, which is automatically generated.

@VaughnVernon
Copy link
Contributor

@danilo-ambrosio Do you mean injected as in passing a constructor parameter from the generated Bootstrap or by another means? Seems like all generated DynamicResourceHandler extenders should have a single constructor generated that takes a Stage and gives it to DynamicResourceHandler via super(stage).

@danilo-ambrosio
Copy link
Contributor

Yes, "injected" means exactly what you've just said, @VaughnVernon . Thanks for clarifying.

@Florian-Schoenherr
Copy link
Contributor

need to ensure some methods implementation

then obviously no annotation 👍
And yes, super(stage)!

@danilo-ambrosio
Copy link
Contributor

@Florian-Schoenherr @VaughnVernon

If you get a chance, please review my changes below and let me know if everything is right:

After the review, could @Florian-Schoenherr please update VLINGO/SCHEMATA REST resources by extending DynamicResourceHandler ?

@Florian-Schoenherr
Copy link
Contributor

Florian-Schoenherr commented Nov 5, 2020

Works as expected! 👍

@VaughnVernon
Copy link
Contributor

@danilo-ambrosio @Florian-Schoenherr I am closing this. Note that I have added support for accessing Context from DynamicResourceHandler. To activate it, code must be generated to include a self reference in routes() when instantiating the ResoureBuilder.

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

4 participants