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

Injector does not respect constructor's private visibility #72

Closed
gissuebot opened this issue Jul 7, 2014 · 13 comments
Closed

Injector does not respect constructor's private visibility #72

gissuebot opened this issue Jul 7, 2014 · 13 comments

Comments

@gissuebot
Copy link

From antti.brax on March 16, 2007 08:17:04

When an instance of the following Service class is created with an
Injector, an instance of the Tool class is created. It would be safer to
assume that this kind of a construction is a programming error.

public class Service {
    @Inject
    public Service(Tool tool) {
    }
}

public class Tool {
    private Tool() {
    }
}

Original issue: http://code.google.com/p/google-guice/issues/detail?id=72

@gissuebot
Copy link
Author

From antti.brax on March 16, 2007 05:45:08

I changed the tool constructor to throw a RuntimeException and here is the stack:

Attachment: gist
   tool.txt

@gissuebot
Copy link
Author

From crazyboblee on March 16, 2007 08:49:58

I see where you're coming from but taking this out would break backward compatibility. :(

Status: WontFix

@gissuebot
Copy link
Author

From kevinb9n on March 16, 2007 09:07:39

Is this kind of fix a possibility for 2.0 or later?

@gissuebot
Copy link
Author

From crazyboblee on March 16, 2007 10:32:09

Well, if we are going to do it, we should do it earlier like Ben said, i.e. 1.1. I'd
rather not mess with this, but I can see people wanting to make a constructor private
as a way of saying, "I do not want Guice to create an implicit binding."

Actually, I would prefer to always require @Inject if the class contains explicit
constructors. Not requiring @Inject was really only intended for implicit constructors.

@gissuebot
Copy link
Author

From kevinb9n on October 06, 2008 12:21:44

Some users are concerned about this. Reopening because it's unclear why it was
closed. Agree with Bob's statement of what should be done.

Status: Accepted

@gissuebot
Copy link
Author

From crazyboblee on October 06, 2008 12:31:18

I definitely think we should bite the bullet and fix this. I actually thought Jesse
already fixed this to some extent.

@gissuebot
Copy link
Author

From limpbizkit on October 06, 2008 13:53:00

We no longer inject private constructors, such as the one for Collections.java.
Removing other non-default constructors is a bit trickier, because we sometimes write
classes that get non-public constructors for default:

For example, consider
  class Foo {}

That class has a package-private constructor.

@gissuebot
Copy link
Author

From limpbizkit on November 02, 2008 01:33:27

(No comment was entered for this change.)

Labels: Milestone-Release2.0

@gissuebot
Copy link
Author

From limpbizkit on December 28, 2008 21:34:10

The current code is a good balance between following the user's intents and ease-of-migration. Here's what
we support, in order of preference:

  1. A single @Inject constructor.
  2. No-args, non-private constructors. Often this is a compiler-generated constructor.
  3. No-args private constructors of private classes.  Often this is a compiler-generated constructor.

If we wanted to tighten the rules further, I think we'd make user code worse. For example, consider an inner
class that exists solely for testing:

public class Stopwatch {

  @Inject
  Stopwatch(Ticker ticker) {
    ...
  }

  public Stopwatch() {
    this(new Ticker());
  }

  // for testing
  static class Ticker {
    long now() {
      return System.currentTimeMillis();
    }
  }
}

If we were to forbid say, default package-private constructors, then the user would need to create a
constructor just for a place to hang the annotation; ie.:

  static class Ticker {

    @Inject
    Ticker() {}

    long now() {
      return System.currentTimeMillis();
    }
  }

That's lame, especially since it will impact lots of existing code. (Just changing our own tests is a large job)

Status: Fixed

@gissuebot
Copy link
Author

From nimbus4321 on January 15, 2009 13:09:58

In order to ensure backwards compatibility with code developed using Guice 1, would
it be possible to have a means of switching off this check ? i.e. So that the new
behaviour would be the default in Guice 2, but could be disabled for maximum
compatibility with code bases developed against Guice 1.

Background to this request:
I came across the new check when testing the codebase for the product I'm working on
against guice-snapshot20081123. There are several public classes with private
constructors in the codebase that are instantiated using Guice. So, this new check
means that Guice 2 is not a "drop-in" replacement for Guice 1 in the codebase  - i.e.
to use Guice 2, the codebase would have to be changed so that the constructors are
annotated with @Inject.

While this change to the product codebase could be made, there is another issue for
us. Guice is also used as part of an extension mechanism for the product, so that
customers can extend and customize it to meet their own requirements. So, some
customers also have public classes with private constructors that are instantiated
via Guice 1. We would like to move the product on to Guice 2 in a forthcoming release
in order to take advantage of some of the great new Guice 2 features. However, it
will greatly complicate the product upgrade process if we have to ask
our customers to make changes to their codebase (i.e. add the @Inject annotation to
private constructors) in order to take the upgrade.

@gissuebot
Copy link
Author

From limpbizkit on January 21, 2009 12:56:11

@nimbus4321 Would you be willing to use a patched version of the Guice .jar ?

@gissuebot
Copy link
Author

From nimbus4321 on January 23, 2009 02:22:46

For testing purposes, have already patched Guice 2 to disable the check. However,
would prefer not to use a fork of the Guice 2 codebase - i.e. would prefer a
supported mechanism to disable the check.

Also, suspect there may be some (few) others in this situation who are unaware of it

  • i.e. who have yet to try Guice 2 (as it is not yet released). So perhaps would be
    worth supporting a means of disabling the check. Is it a possibility ?

@gissuebot
Copy link
Author

From nimbus4321 on January 29, 2009 05:03:29

See also this thread in the user group on this issue : http://groups.google.com/group/google-guice/browse_thread/thread/defa5ed074ac5aff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant