GithubHelp home page GithubHelp logo

Comments (12)

jhaber avatar jhaber commented on August 24, 2024

#48 is related to this. You could either check that the class isn't an interface or abstract class, but retrieving an interface/abstract class from the injector isn't guaranteed to fail (you could bind the interface to an impl in your module). Alternatively, you could retrieve from the injector in a try/catch and swallow any Guice errors, but that could mask actual issues. I left a comment here detailing my thoughts, let me know what you think. The only other thing that comes to mind is to make the logic something like:

if it's not an interface or abstract class:
try to get it from the injector
else if injector.getExistingBinding returns a non-null result:
return binding.getProvider().get()
else if annotated with @ImplementedBy or @ProvidedBy:
use the value in the annotation to get an instance from the injector
else log at info level that the class is being ignored

This would handle the case where you make an explicit binding for the interface/abstract class (or an implicit binding using @ImplementedBy or @ProvidedBy) and propagate any errors when retrieving these from the injector, but it would ignore any other interfaces/abstract classes encountered which should handle your use-case

from dropwizard-guice.

scho avatar scho commented on August 24, 2024

I tried to implement it myself and I came up with an idea that is different from yours. Why not check if there are any subtypes for the given subtype of InjectableHealthCheck? And then only instantiate it if there aren't any. Something like:

if (reflections.getSubTypesOf(healthCheck).size() != 0) {
  continue;
}

In my opinion it doesn't make sense to instantiate any health check class that is not final/has any subtypes.
Of course, you would loose the ability to have different implementations for one abstract subclass of InjectableHealthCheck. But that's not possible either now.

Another idea that I had is having a default implementation for getName() that derives its result from the class name. Because that's what you want most of the time anyways:

public abstract class NamedHealthCheck extends InjectableHealthCheck {

   @Override
   public String getName() {
      return Introspector.decapitalize(getClass().getSimpleName()).replace("HealthCheck", "");
   }

}

What do you think about this? If you're okay with it I'll send you a PR.

from dropwizard-guice.

scho avatar scho commented on August 24, 2024

Another thought on this.

Why not doing:

if (Modifier.isAbstract(healthCheck.getModifiers())) {
  continue;
}

It wouldn't not take away anything that is not already there yet. E.g. in my opinion you can not bind an implementation of an abstract class extending InjectableHealthCheck without adding the same healthcheck twice.

from dropwizard-guice.

jhaber avatar jhaber commented on August 24, 2024

Are you taking into account that AutoConfig is limited to a certain set of packages? You can have an abstract health check in an autoconfig'ed package and the implementation in a different package

from dropwizard-guice.

scho avatar scho commented on August 24, 2024

I understand that that is a problem. But isn't that the case at the moment? Wouldn't checking if a class is abstract only add value?

from dropwizard-guice.

jhaber avatar jhaber commented on August 24, 2024

Currently if I have an abstract healthcheck in an autoconfig package and an implementation in a different package bound via Guice, everything works fine because autoconfig finds the abstract class and gets the impl from Guice. If we added the snippet you posted

if (Modifier.isAbstract(healthCheck.getModifiers())) {
  continue;
}

wouldn't it break this case by no longer adding the healthcheck?

from dropwizard-guice.

scho avatar scho commented on August 24, 2024

Yes, you are right, it would break it.
I am curious though, in what case do you need different implementations for a healthcheck? Do you support different databases?

from dropwizard-guice.

scho avatar scho commented on August 24, 2024

I have another thought on this:
I have an abstract class HostReachableHealthCheck which extends InjectableHealthCheck.
There are different classes HostOneReachableHealthCheck, HostTwoReachableHealthCheck etc., all extending HostReachableHealthCheck.

HostOneReachableHealthCheck (an all the others) is within a AutoConfig'uired package, but HostReachableHealthCheck is not. The problem is: None of my concrete health checks is found (I assume because HostReachableHealthCheck is not AutoConfig'uired).

My suggestion would be then: Why not using the @Provider method in order to find all health checks. Or would you think this is against the whole idea of AutoConfig?

from dropwizard-guice.

BenRomberg avatar BenRomberg commented on August 24, 2024

@jhaber any news regarding this? It's causing major pain for me not to be able to use abstract classes for Tasks and HealthChecks as well.

Is the use case you described in your last comment really relevant? IMHO it's worth giving up backwards compatibility if it only concerns this use case.

Another idea would be to introduce an annotation that signals that the class should be skipped. Something like @GuiceIgnore maybe? Could be useful for other scenarios as well, and shouldn't be restricted to abstract classes only.

from dropwizard-guice.

jhaber avatar jhaber commented on August 24, 2024

I did a first pass at this in 2ea01f2. I just released as version 0.8.1.2, let me know if it solves your issue

from dropwizard-guice.

BenRomberg avatar BenRomberg commented on August 24, 2024

Works smoothly for me, thanks a lot for the quick response! :-)

from dropwizard-guice.

jhaber avatar jhaber commented on August 24, 2024

Glad to hear it!

from dropwizard-guice.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.