Implementing a Singleton Builder in Dagger - java

I have a class that I would like to inject via Dagger. It requires a builder, as some of its parameters are only known at runtime. I would also like this class to be a singleton.
That is to say, several parts of our codebase require the instance of this class, but only one part of the codebase actually knows how to set it up.
The setup happens early on in the application - before anyone would actually try to use the singleton - but after Dagger has already initialized its root component.
What is the right way for other parts of the code to get access to the object?
class S {
private S(Foobar foobar) {
// ...
}
#Singleton
public static class Builder {
Foobar foobar;
#Inject
public Builder() {}
public Builder setFoobar(Foobar foobar) {
this.foobar = foobar;
}
public S build() {
return new S(foobar);
}
}
}
class Main {
private Foobar foobar = new Foobar();
private final S s;
#Inject
public Main(S.Builder sBuilder) {
s = sBuilder.setFoobar(foobar).build();
}
}
class Other {
private final S s;
#Inject
public Other(/* What do I put here to get access to S? */) {
}
Edit:
For clarity, let me state that Foobar in this example is created early in the application, but after Dagger and the high level structure of the app has been instantiated. This specific program is an Android app; the Foobar in this case a View that is inflated, and S a controller for that View.
There will only ever be one Foobar and one S. Various parts of our code want to be able to communicate with S, but only one part of our code can actually create it.

You can use BindsInstance for that https://dagger.dev/api/2.10/dagger/BindsInstance.html
Your Application creates the RootComponent. During creation it should provide the instance of the Foobar. Let's take a look at the pseudocode
class S {
private S(Foobar foobar) {
// ...
}
public static class Builder {
Foobar foobar;
public Builder() {}
public Builder setFoobar(Foobar foobar) {
this.foobar = foobar;
}
public S build() {
return new S(foobar);
}
}
}
#Module
public static class RootModule {
#Provides
#Singleton
public static S provideS(Foobar foobar) {
return new S.Builder().setFoobar(foobar).build();
}
}
#Singleton
#Component(module = {RootModule.class})
public interface RootComponent {
#Component.Factory
interface Factory {
public RootComponent create(#BindsInstance Foobar foobar)
}
}
public class Application {
private RootComponent createComponent() {
return DaggerRootComponent.factory().create(new Foobar())
}
}
Update
This specific program is an Android app; the Foobar in this case a View that is inflated, and S a controller for that View.
I strongly discourage you from keeping a reference to a View. This might produce subtle bugs and memory leaks. Instead I suggest you to introduce some sort of event bus which will be a singleton in your Dagger graph and shared between S (view controller) and consumers. This even bus will be used for communication between consumers and S (view controller).

Building off of a hint I gleamed from #MyDogTom's answer, introducing our first Subcomponent was the solution.
Wait to construct the S until after Foobar has been constructed. Then initialize a subcomponent, passing S to its Builder, and use the subcomponent to construct Other.
#Subcomponent
public interface MySubComponent {
#Subcomponent.Builder
interface Builder {
#BindsInstance Builder s(S s);
StatusBarComponent build();
}
/**
* Scope annotation for singleton items within the MySubComponent.
*/
#Documented
#Retention(RUNTIME)
#Scope
#interface MySubComponentScope {}
#MySubComponentScope
Ohter getOther();
}
// Attach MySubComponent to Dagger where appropriate, per their documentation.
// Then, in Main, do something like the following:
class Main {
private final MySubComponent.Builder mySubComponentBuilder;
private final S.Builder sBuilder;
private Foobar foobar;
#Inject
public Main(MySubComponent.Builder mySubComponentBuilder, S.Builder sBuilder) {
this.mySubComponentBuilder = mySubComponentBuilder;
this.sBuilder = sBuilder;
}
// At some point, foobar gets created. Then we call the following method.
private void afterInit();
S s = sBuilder.setFoobar(foobar).build();
Other other = mySubComponentBuilder.s(s).build().getOther();
}
}
This is a slightly contrived example, obviously, but demonstrates the solution to the problem.

Related

Swappable modules with Dagger 2

So I have some code that runs an algorithm, say with an AlgoRunner class. Now this AlgoRunner class can be implemented in multiple ways to run different algorithms using Algo classes. I want to use Dagger 2 to provide different implementations of the AlgoRunner class to a "Manager" class that passes input to AlgoRunner as well as other components that it manages.
Question
I have the following right now, but I'm not sure if this is the correct way, mainly because of that empty AlgoRunnerProvider module. Is that any other way to achieve what I'm trying to do? Or to simplify what I have?
Should I just create different components, OneAlgoRunnerComponent and TwoAlgoRunnerComponent and inject the Manager from each of those?
The class that constructs the Manager instance uses this component to inject the AlgoRunner into that instance so that the Manager can pass it the inputs.
#Component(
modules = {
AlgoRunnerProvider.class
}
)
public interface AlgoRunnerComponent {
void inject(Manager manager);
AlgoRunner getAlgoRunner();
}
AlgoRunnerProvider Module
#Module
public class AlgoRunnerProvider {
#Provides
public AlgoRunner getAlgoRunner() {
return null;
}
}
OneAlgoRunnerProvider, that overrides the provides method in AlgoRunnerProvider.
Could have a TwoAlgoRunnerProvider as well, that does the same thing and provides TwoAlgoRunner, as long as that extends AlgoRunner.
public class OneAlgoRunnerProvider extends AlgoRunnerProvider {
private final OneAlgo algo;
public OneAlgoRunnerProvider(OneAlgo algo) {
this.algo = algo;
}
#Override
public OneAlgoRunner getAlgoRunner() {
return new OneAlgoRunner(algo);
}
}
All this is used like this right now:
AlgoRunnerComponent build = DaggerAlgoRunnerComponent.builder()
.algoRunnerProvider(new OneAlgoRunnerProvider(new OneAlgo()))
// .algoRunnerProvider(new TwoAlgoRunnerProvider(new TwoAlgo()))
.build();
Manager manager = managerComponent.getManager();
build.inject(manager);
Truth.assertThat(manager.algoRunner).isInstanceOf(OneAlgoRunner.class);
// Truth.assertThat(manager.algoRunner).isInstanceOf(OneAlgoRunner.class);
Thanks a lot!
The dagger framework is used to handle object creation for you. If you start doing some sort of initialization in one of your classes you wish to provide, there is probably something not as it is supposed to be (see getAlgoRunner()).
If you have different types that you want to provide at runtime, you want a factory of some sorts to create the correct object. Enter dagger.
You have multiple ways of achieving what you want. Basically, the module should handle the object creation:
#Module
public class AlgoRunnerProvider {
#Provides
public AlgoRunner getAlgoRunner() {
// todo create the correct type
return null;
}
}
1. #Named annotation (or some other Qualifier)
If you know at compile time which class is going to need which type, you should use qualifiers.
#Named("Version1")
#Inject
AlgoRunner mRunner;
You then just can provide different implementations from your module:
#Provides
#Named("Version1")
public AlgoRunner getAlgoRunner() {
return new Version1AlgoRunner();
}
#Provides
#Named("OtherVersion")
public AlgoRunner getAlgoRunner(Depends someOtherDependency) {
return new OtherVersionAlgoRunner(someOtherDependency);
}
2. Switching at runtime
While you could always use the first option by creating multiple classes with different dependencies, you might want to be able to chose at runtime. For this, you need to pass in some argument to your module:
#Module
public class AlgoRunnerProvider {
private final int mType;
public AlgoRunnerProvider(int type) {
mType = type;
}
#Provides
public AlgoRunner getAlgoRunner() {
if(mType == TYPE_A) {
return new Version1AlgoRunner();
} else {
return new OtherVersionAlgoRunner();
}
}
}
With this variant you still have your creation logic inside your module, where your dependencies come from.
3. Use different modules
Another approach would be to use different modules. This will only be a clean solution if determined at compile time (different classes using different modules) and not some choosing logic at runtime in the same class.
If you start writing code like if typeA then moduleA else moduleB you should probably stop and do something else.
You can use the same component but create it using different modules for different classes by using good old inheritance. Every module just provides its implementation of AlgoRunner.
// one class using one module to get a specific behavior
public class MyClassVersionA {
public void onCreate(Bundle saved) {
component.myModule(new MyModuleVersionA()).build();
}
}
// another class using a different module to get a different behavior
public class MyClassSomethingElse {
public void onCreate(Bundle saved) {
component.myModule(new MyModuleSomethingElse()).build();
}
}
You would then just subclass your module accordingly like so
// did not test the following, something like this...
public abstract class MyModule {
#Provides
public AlgoRunner getAlgoRunner();
}
public class MyModuleVersionA extends MyModule {
#Provides
#Override
public AlgoRunner getAlgoRunner() {
return new Version1AlgoRunner();
}
}
public class MyModuleSomethingElse extends MyModule {
#Provides
#Override
public AlgoRunner getAlgoRunner() {
return new SomeOtherAlgoRunner();
}
}
There are probably even more possibilities, especially if starting to mix those approaches, but I think those 3 to be the basic tools that you can use.

Creating and managing unique instances of class in Java that can be accessed by different users

I have a programming problem that I want to know if it can be solved using Java design techniques. I have class Service and I have a class Client. A client requests a service and if it's not already existing, then it will be created (i.e. new service object). If the service has been created (i.e by a different client or even the same client), then the Service class will not create a new object. Instead, the client can be added to the service (if not already added). Other fields and methods of the Service class will be applied to clients of the same service.
public class Service {
private String service;
private ArrayList<Integer> clients;
//.... other field
public Service (String s){
this.service = s;
clients = new ArrayList<>;
}
public void addClient(int c){
clients.add(c);
}
//..other methods
}
public class Client {
private int clientID;
private ArrayList<String> services;
public Client(int id){
clientID = id;
services = new ArrayList<>;
}
public void addService(String s){
services.add(s);
}
public void requestService() {
for(int i=0; i<services.size();i++)
Service s = new Service(services.get(i));
}
}
The problem with the above approach is that new service objects with the same service would be created by different clients.
I'm currently reading up on on static factory. As far as my research goes:
public class Service(){
private Service(){
}
public static Service createService(String service){
if (/*service doesn't exist*/)
return new Serivce();
else
return null;
}
//....
}
This above code would prevent creating a new object instance. However, if service already exists and therefore returns null, then a new client cannot join (or use) that particular service.
I think what you're looking for is the typical lazy singleton pattern. Have a look here with focus on the Initialization-on-demand holder idiom which is the best approach in my opinion as it's 100% thread safe.
public class Service {
// Private constructor. Prevents instantiation from other classes.
private Service() {
}
// Initializes Service singleton.
private static class SingletonHolder {
private static final Service INSTANCE = new Service();
}
// gets the one and only instance of Service
public static Service getInstance() {
return SingletonHolder.INSTANCE;
}
}
EDIT:
Looking at you static factory code, it looks like you're actually looking for a Service container that provides one and only service instances for a particular key (service name, or service class for better type safety) you pass. Below you'll find a very basic not thread-safe implementation using classes as key. There are a lot other better thread-safe implementations if you google around for "thread-safe multitons" or similar. However if you're now on a green field, I deeply recommend to make use of a dependency injection framework, which already does the whole job for you apart from bringing many other benefits. I'm a fan of Google's Guice in particular but the decision what to use heavily depends on your project. If you need help for the decision I suggest posting a new thread with the details of your project and what you need this service container for.
public class ServiceContainer {
private final Map<Class<?>, Service> map = new HashMap<>();
// Private constructor. Prevents instantiation from other classes.
private ServiceContainer() {
}
// ServiceContainer singleton.
private static class SingletonHolder {
private static final ServiceContainer INSTANCE = new ServiceContainer();
}
// gets the one and only instance for a particular Service class
#SuppressWarnings("unchecked")
public static <T extends Service> T getInstance(final Class<T> serviceClass) {
// init service if not initialized yet
if (!SingletonHolder.INSTANCE.map.containsKey(serviceClass)) {
SingletonHolder.INSTANCE.map.put(serviceClass, createService(serviceClass));
}
return (T)SingletonHolder.INSTANCE.map.get(serviceClass);
}
private static <T extends Service> T createService(final Class<T> serviceClass) {
try {
return serviceClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
// please handle this exception properly
throw new RuntimeException(e);
}
}
}

Guice won't intercept annotated methods

I have a situation where Guice is working for some bindings, and not at all for others. Clearly I am using the API incorrectly.
In part, it's probably because I'm trying to get too "fancy" with how I'm using Guice. I've created an inheritance tree of Modules and I think I've gotten too clever (or foolish!) for my own good.
Before you look at the code below, just please understand my intention, which was to provide a reusable Module that I can place in a JAR and share across multiple projects. This abstract, reusable Module would provide so-called "default bindings" that any implementing Module would automatically honor. Things like an AOP MethodInterceptor called Profiler, which looks for methods annotated with #Calibrated and automatically logs how long it took for that method to execute, etc.
Observe the following:
#Target({ ElementType.METHOD })
#RetentionPolicy(RetentionPolicy.RUNTIME)
#BindingAnnotation
public #interface Calibrated{}
public class Profiler implement MethodInterceptor {
#Override
public Object invoke(MethodInvocation arg0) throws Throwable {
// Eventually it will calculate and log the amount of time
// it takes an intercepted method to execute, hence "Profiler".
System.out.println("Intercepted!");
return arg0.proceed();
}
}
public abstract class BaseModule implements Module {
private Binder binder;
public BaseModule() {
super();
}
public abstract void bindDependencies();
#Override
public void configure(Binder bind) {
// Save the binder Guice passes so our subclasses can reuse it.
setBinder(bind);
// TODO: For now do nothing, down the road add some
// "default bindings" here.
// Now let subclasses define their own bindings.
bindDependencies();
}
// getter and setter for "binder" field
// ...
}
public abstract class AbstractAppModule extends BaseModule {
/* Guice Injector. */
private Injector injector;
// Some other fields (unimportant for this code snippet)
public AbstractAppModule() {
super();
}
// getters and setters for all fields
// ...
public Object inject(Class<?> classKey) {
if(injector == null)
injector = Guice.createInjector(this);
return injector.getInstance(classKey);
}
}
So, to use this small library:
public class DummyObj {
private int nonsenseInteger = -1;
// getter & setter for nonsenseInteger
#Calibrated
public void shouldBeIntercepted() {
System.out.println("I have been intercepted.");
}
}
public class MyAppModule extends AbstractAppModule {
private Profiler profiler;
// getter and setter for profiler
#Override
public void bindDependencies() {
DummyObj dummy = new DummyObj();
dummy.setNonsenseInteger(29);
// When asked for a DummyObj.class, return this instance.
getBinder().bind(DummyObj.class).toInstance(dummy);
// When a method is #Calibrated, intercept it with the given profiler.
getBinder().bindInterceptor(Matchers.any(),
Matchers.annotatedWith(Calibrated.class),
profiler);
}
}
public class TestGuice {
public static void main(String[] args) {
Profiler profiler = new Profiler();
MyAppModule mod = new MyAppModule();
mod.setProfiler(profiler);
// Should return the bounded instance.
DummyObj dummy = (DummyObj.class)mod.inject(DummyObj.class);
// Should be intercepted...
dummy.shouldBeIntercepted();
System.out.println(dummy.getNonsenseInteger());
}
}
This is a lot of code so I may have introduced a few typos when keying it all in, but I assure you this code compiles and throws no exceptions when ran.
Here's what happens:
The #Calibrated shouldBeIntercepted() method is not intercepted; but...
The console output shows the dummy's nonsense integer as...29!!!!
So, regardless of how poor a design you may think this is, you can't argue that Guice is indeed working for 1 binding (the instance binding), but not the AOP method interception.
If the instance binding wasn't working, then I would happily revisit my design. But something else is going on here. I'm wondering if my inheritance tree is throwing the Binder off somehow?
And I've verified that I am binding the interceptor to the annotation correctly: I created another package where I just implement Module (instead of this inheritance tree) and use the same annotation, the same Profiler, and it works perfectly fine.
I've used Injector.getAllBindings() to print out the map of all my MyAppModule's bindings as Strings. Nothing is cropping up as the clear source of this bug.
Interception only works on Objects created by Guice (see "Limitations" http://code.google.com/p/google-guice/wiki/AOP#Limitations). You are using "new" to create the DummyObj, so no matter how clever your Module is Set up, the instance is created Outside guice.
Here's a little snipplet based on your coding. (I use your Calibrated Annotation, but had everything else in one class. You should have a look at "AbstractModule". It saves a lot of manual stuff you did with your Module-Hierarchy.
public class MyModule extends AbstractModule implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Intercepted#invoke!");
return methodInvocation.proceed();
}
#Override
protected void configure() {
bind(Integer.class).annotatedWith(Names.named("nonsense")).toInstance(29);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Calibrated.class), this);
}
public static void main(String... args) {
Dummy dummy = Guice.createInjector(new MyModule()).getInstance(Dummy.class);
dummy.doSomething();
System.out.println(dummy.getNonsense());
}
}
And my Dummy:
public class Dummy {
#Inject
#Named("nonsense")
private int nonsense;
public int getNonsense() {
return nonsense;
}
public void setNonsense(int nonsense) {
this.nonsense = nonsense;
}
#Calibrated
public void doSomething() {
System.out.println("I have been intercepted!");
}
}
So you see? I never use the word "new" (except for the Module ....). I let Guice handle the Dummy-Object and just configure the value for the nonsense int, which is then injected.
Output:
Intercepted#invoke!
I have been intercepted!
29

How do I mock a method of a class' member field?

I'm using Java 6 and Mockito 1.8.5. I want to mock a class' member field's method, but I can't figure out how. I have these classes ...
public class CacheService implements CacheCallback {
private final Cache cache;
...
public static CacheService getInstance() {
return INSTANCE;
}
private CacheService() {
cache = new DefaultCacheImpl();
}
public boolean saveNodes(final Map<Long, XmlNode> nodeMap) {
...
cache.saveNodes(nodeMap);
}
...
}
public class DefaultCacheImpl implements Cache {
...
public void saveNodes(Map<Long, XmlNode> xmlNodes) {
dao.updateDB(xmlNodes);
}
...
}
I can't figure out how to mock the "cache" member field's method "saveNodes". I'm mocking the method below, but because there is no setter in the CacheService class for the field, I can't figure out how to inject my mock ..
public class PopulateCacheServiceImpl extends RemoteServiceServlet implements PopulateCacheService {
...
public Boolean initCache() {
boolean ret = false;
try {
setupMocks();
CacheService.getInstance().startCache();
PopulateCache.addTestEntriesToCache();
ret = true;
} catch (Exception e) {
e.printStackTrace(System.err);
ret = false;
} // try
return ret;
} // initCache
private void setupMocks() {
DefaultCacheImpl cache = mock(DefaultCacheImpl.class);
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(cache).saveNodes(Matchers.anyMap());
} // setupMocks
}
Are there any other ways to do this with Mockito? Thanks, - Dave
The problem is in this line:
cache = new DefaultCacheImpl();
If you construct a cache object inside your CacheService, they are tightly coupled. You can not use the CacheService with another cache implementation.
Instead, pass the cache implementation to the constructor:
public CacheService(Cache cacheImpl) {
this.cache = cacheImpl;
}
This allows the CacheService to use any Cache implementation.
What about making two constructors? The one you have would stay there. Another one would let you pass in the Cache implementation and allow you to test the class. The new constructor can have protected access to limit which classes can use it.
If you can change the source, decopule those classes. Get rid of cache = new DefaultCacheImpl(); from constructor as Sjoerd suggested.
If you can't - use PowerMock to mock the constructor of DefaultCacheImpl. I must say that this is really ugly solution (the only uglier is mocking static initialization code).
Note:
Your code is an answer to popular question "Why do I need dependency injection for?". I think people were looking at code like this when they invented DI.

Is there a way to simulate the C++ 'friend' concept in Java?

I would like to be able to write a Java class in one package which can access non-public methods of a class in another package without having to make it a subclass of the other class. Is this possible?
Here is a small trick that I use in JAVA to replicate C++ friend mechanism.
Lets say I have a class Romeo and another class Juliet. They are in different packages (family) for hatred reasons.
Romeo wants to cuddle Juliet and Juliet wants to only let Romeo cuddle her.
In C++, Juliet would declare Romeo as a (lover) friend but there are no such things in java.
Here are the classes and the trick :
Ladies first :
package capulet;
import montague.Romeo;
public class Juliet {
public static void cuddle(Romeo.Love love) {
Objects.requireNonNull(love);
System.out.println("O Romeo, Romeo, wherefore art thou Romeo?");
}
}
So the method Juliet.cuddle is public but you need a Romeo.Love to call it. It uses this Romeo.Love as a "signature security" to ensure that only Romeo can call this method and checks that the love is real so that the runtime will throw a NullPointerException if it is null.
Now boys :
package montague;
import capulet.Juliet;
public class Romeo {
public static final class Love { private Love() {} }
private static final Love love = new Love();
public static void cuddleJuliet() {
Juliet.cuddle(love);
}
}
The class Romeo.Love is public, but its constructor is private. Therefore anyone can see it, but only Romeo can construct it. I use a static reference so the Romeo.Love that is never used is only constructed once and does not impact optimization.
Therefore, Romeo can cuddle Juliet and only he can because only he can construct and access a Romeo.Love instance, which is required by Juliet to cuddle her (or else she'll slap you with a NullPointerException).
The designers of Java explicitly rejected the idea of friend as it works in C++. You put your "friends" in the same package. Private, protected, and packaged security is enforced as part of the language design.
James Gosling wanted Java to be C++ without the mistakes. I believe he felt that friend was a mistake because it violates OOP principles. Packages provide a reasonable way to organize components without being too purist about OOP.
NR pointed out that you could cheat using reflection, but even that only works if you aren't using the SecurityManager. If you turn on Java standard security, you won't be able to cheat with reflection unless you write security policy to specifically allow it.
The 'friend' concept is useful in Java, for example, to separate an API from its implementation. It is common for implementation classes to need access to API class internals but these should not be exposed to API clients. This can be achieved using the 'Friend Accessor' pattern as detailed below:
The class exposed through the API:
package api;
public final class Exposed {
static {
// Declare classes in the implementation package as 'friends'
Accessor.setInstance(new AccessorImpl());
}
// Only accessible by 'friend' classes.
Exposed() {
}
// Only accessible by 'friend' classes.
void sayHello() {
System.out.println("Hello");
}
static final class AccessorImpl extends Accessor {
protected Exposed createExposed() {
return new Exposed();
}
protected void sayHello(Exposed exposed) {
exposed.sayHello();
}
}
}
The class providing the 'friend' functionality:
package impl;
public abstract class Accessor {
private static Accessor instance;
static Accessor getInstance() {
Accessor a = instance;
if (a != null) {
return a;
}
return createInstance();
}
private static Accessor createInstance() {
try {
Class.forName(Exposed.class.getName(), true,
Exposed.class.getClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
return instance;
}
public static void setInstance(Accessor accessor) {
if (instance != null) {
throw new IllegalStateException(
"Accessor instance already set");
}
instance = accessor;
}
protected abstract Exposed createExposed();
protected abstract void sayHello(Exposed exposed);
}
Example access from a class in the 'friend' implementation package:
package impl;
public final class FriendlyAccessExample {
public static void main(String[] args) {
Accessor accessor = Accessor.getInstance();
Exposed exposed = accessor.createExposed();
accessor.sayHello(exposed);
}
}
There are two solutions to your question that don't involve keeping all classes in the same package.
The first is to use the Friend Accessor/Friend Package pattern described in (Practical API Design, Tulach 2008).
The second is to use OSGi. There is an article here explaining how OSGi accomplishes this.
Related Questions: 1, 2, and 3.
As far as I know, it is not possible.
Maybe, You could give us some more details about Your design. Questions like these are likely the result of design flaws.
Just consider
Why are those classes in different packages, if they are so closely related?
Has A to access private members of B or should the operation be moved to class B and triggered by A?
Is this really calling or is event-handling better?
eirikma's answer is easy and excellent. I might add one more thing: instead of having a publicly accessible method, getFriend() to get a friend which cannot be used, you could go one step further and disallow getting the friend without a token: getFriend(Service.FriendToken). This FriendToken would be an inner public class with a private constructor, so that only Service could instantiate one.
Here's a clear use-case example with a reusable Friend class. The benefit of this mechanism is simplicity of use. Maybe good for giving unit test classes more access than the rest of the application.
To begin, here is an example of how to use the Friend class.
public class Owner {
private final String member = "value";
public String getMember(final Friend friend) {
// Make sure only a friend is accepted.
friend.is(Other.class);
return member;
}
}
Then in another package you can do this:
public class Other {
private final Friend friend = new Friend(this);
public void test() {
String s = new Owner().getMember(friend);
System.out.println(s);
}
}
The Friend class is as follows.
public final class Friend {
private final Class as;
public Friend(final Object is) {
as = is.getClass();
}
public void is(final Class c) {
if (c == as)
return;
throw new ClassCastException(String.format("%s is not an expected friend.", as.getName()));
}
public void is(final Class... classes) {
for (final Class c : classes)
if (c == as)
return;
is((Class)null);
}
}
However, the problem is that it can be abused like so:
public class Abuser {
public void doBadThings() {
Friend badFriend = new Friend(new Other());
String s = new Owner().getMember(badFriend);
System.out.println(s);
}
}
Now, it may be true that the Other class doesn't have any public constructors, therefore making the above Abuser code impossible. However, if your class does have a public constructor then it is probably advisable to duplicate the Friend class as an inner class. Take this Other2 class as an example:
public class Other2 {
private final Friend friend = new Friend();
public final class Friend {
private Friend() {}
public void check() {}
}
public void test() {
String s = new Owner2().getMember(friend);
System.out.println(s);
}
}
And then the Owner2 class would be like this:
public class Owner2 {
private final String member = "value";
public String getMember(final Other2.Friend friend) {
friend.check();
return member;
}
}
Notice that the Other2.Friend class has a private constructor, thus making this a much more secure way of doing it.
The provided solution was perhaps not the simplest. Another approach is based on the same idea as in C++: private members are not accessible outside the package/private scope, except for a specific class that the owner makes a friend of itself.
The class that needs friend access to a member should create a inner public abstract "friend class" that the class owning the hidden properties can export access to, by returning a subclass that implement the access-implementing methods. The "API" method of the friend class can be private so it is not accessible outside the class that needs friend access. Its only statement is a call to an abstract protected member that the exporting class implements.
Here's the code:
First the test that verifies that this actually works:
package application;
import application.entity.Entity;
import application.service.Service;
import junit.framework.TestCase;
public class EntityFriendTest extends TestCase {
public void testFriendsAreOkay() {
Entity entity = new Entity();
Service service = new Service();
assertNull("entity should not be processed yet", entity.getPublicData());
service.processEntity(entity);
assertNotNull("entity should be processed now", entity.getPublicData());
}
}
Then the Service that needs friend access to a package private member of Entity:
package application.service;
import application.entity.Entity;
public class Service {
public void processEntity(Entity entity) {
String value = entity.getFriend().getEntityPackagePrivateData();
entity.setPublicData(value);
}
/**
* Class that Entity explicitly can expose private aspects to subclasses of.
* Public, so the class itself is visible in Entity's package.
*/
public static abstract class EntityFriend {
/**
* Access method: private not visible (a.k.a 'friendly') outside enclosing class.
*/
private String getEntityPackagePrivateData() {
return getEntityPackagePrivateDataImpl();
}
/** contribute access to private member by implementing this */
protected abstract String getEntityPackagePrivateDataImpl();
}
}
Finally: the Entity class that provides friendly access to a package private member only to the class application.service.Service.
package application.entity;
import application.service.Service;
public class Entity {
private String publicData;
private String packagePrivateData = "secret";
public String getPublicData() {
return publicData;
}
public void setPublicData(String publicData) {
this.publicData = publicData;
}
String getPackagePrivateData() {
return packagePrivateData;
}
/** provide access to proteced method for Service'e helper class */
public Service.EntityFriend getFriend() {
return new Service.EntityFriend() {
protected String getEntityPackagePrivateDataImpl() {
return getPackagePrivateData();
}
};
}
}
Okay, I must admit it is a bit longer than "friend service::Service;" but it might be possible to shorten it while retaining compile-time checking by using annotations.
In Java it is possible to have a "package-related friendness".
This can be userful for unit testing.
If you do not specify private/public/protected in front of a method, it will be "friend in the package".
A class in the same package will be able to access it, but it will be private outside the class.
This rule is not always known, and it is a good approximation of a C++ "friend" keyword.
I find it a good replacement.
I think that friend classes in C++ are like inner-class concept in Java. Using inner-classes
you can actually define an enclosing class and an enclosed one. Enclosed class has full access to the public and private members of it's enclosing class.
see the following link:
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Not using a keyword or so.
You could "cheat" using reflection etc., but I wouldn't recommend "cheating".
I think, the approach of using the friend accessor pattern is way too complicated. I had to face the same problem and I solved using the good, old copy constructor, known from C++, in Java:
public class ProtectedContainer {
protected String iwantAccess;
protected ProtectedContainer() {
super();
iwantAccess = "Default string";
}
protected ProtectedContainer(ProtectedContainer other) {
super();
this.iwantAccess = other.iwantAccess;
}
public int calcSquare(int x) {
iwantAccess = "calculated square";
return x * x;
}
}
In your application you could write the following code:
public class MyApp {
private static class ProtectedAccessor extends ProtectedContainer {
protected ProtectedAccessor() {
super();
}
protected PrivateAccessor(ProtectedContainer prot) {
super(prot);
}
public String exposeProtected() {
return iwantAccess;
}
}
}
The advantage of this method is that only your application has access to the protected data. It's not exactly a substitution of the friend keyword. But I think it's quite suitable when you write custom libraries and you need to access protected data.
Whenever you have to deal with instances of ProtectedContainer you can wrap your ProtectedAccessor around it and you gain access.
It also works with protected methods. You define them protected in your API. Later in your application you write a private wrapper class and expose the protected method as public. That's it.
If you want to access protected methods you could create a subclass of the class you want to use that exposes the methods you want to use as public (or internal to the namespace to be safer), and have an instance of that class in your class (use it as a proxy).
As far as private methods are concerned (I think) you are out of luck.
I agree that in most cases the friend keyword is unnecessary.
Package-private (aka. default) is sufficient in most cases where you have a group of heavily intertwined classes
For debug classes that want access to internals, I usually make the method private and access it via reflection. Speed usually isn't important here
Sometimes, you implement a method that is a "hack" or otherwise which is subject to change. I make it public, but use #Deprecated to indicate that you shouldn't rely on this method existing.
And finally, if it really is necessary, there is the friend accessor pattern mentioned in the other answers.
A method I've found for solving this problem is to create an accessor object, like so:
class Foo {
private String locked;
/* Anyone can get locked. */
public String getLocked() { return locked; }
/* This is the accessor. Anyone with a reference to this has special access. */
public class FooAccessor {
private FooAccessor (){};
public void setLocked(String locked) { Foo.this.locked = locked; }
}
private FooAccessor accessor;
/** You get an accessor by calling this method. This method can only
* be called once, so calling is like claiming ownership of the accessor. */
public FooAccessor getAccessor() {
if (accessor != null)
throw new IllegalStateException("Cannot return accessor more than once!");
return accessor = new FooAccessor();
}
}
The first code to call getAccessor() "claims ownership" of the accessor. Usually, this is code that creates the object.
Foo bar = new Foo(); //This object is safe to share.
FooAccessor barAccessor = bar.getAccessor(); //This one is not.
This also has an advantage over C++'s friend mechanism, because it allows you to limit access on a per-instance level, as opposed to a per-class level. By controlling the accessor reference, you control access to the object. You can also create multiple accessors, and give different access to each, which allows fine-grained control over what code can access what:
class Foo {
private String secret;
private String locked;
/* Anyone can get locked. */
public String getLocked() { return locked; }
/* Normal accessor. Can write to locked, but not read secret. */
public class FooAccessor {
private FooAccessor (){};
public void setLocked(String locked) { Foo.this.locked = locked; }
}
private FooAccessor accessor;
public FooAccessor getAccessor() {
if (accessor != null)
throw new IllegalStateException("Cannot return accessor more than once!");
return accessor = new FooAccessor();
}
/* Super accessor. Allows access to secret. */
public class FooSuperAccessor {
private FooSuperAccessor (){};
public String getSecret() { return Foo.this.secret; }
}
private FooSuperAccessor superAccessor;
public FooSuperAccessor getAccessor() {
if (superAccessor != null)
throw new IllegalStateException("Cannot return accessor more than once!");
return superAccessor = new FooSuperAccessor();
}
}
Finally, if you'd like things to be a bit more organized, you can create a reference object, which holds everything together. This allows you to claim all accessors with one method call, as well as keep them together with their linked instance. Once you have the reference, you can pass the accessors out to the code that needs it:
class Foo {
private String secret;
private String locked;
public String getLocked() { return locked; }
public class FooAccessor {
private FooAccessor (){};
public void setLocked(String locked) { Foo.this.locked = locked; }
}
public class FooSuperAccessor {
private FooSuperAccessor (){};
public String getSecret() { return Foo.this.secret; }
}
public class FooReference {
public final Foo foo;
public final FooAccessor accessor;
public final FooSuperAccessor superAccessor;
private FooReference() {
this.foo = Foo.this;
this.accessor = new FooAccessor();
this.superAccessor = new FooSuperAccessor();
}
}
private FooReference reference;
/* Beware, anyone with this object has *all* the accessors! */
public FooReference getReference() {
if (reference != null)
throw new IllegalStateException("Cannot return reference more than once!");
return reference = new FooReference();
}
}
After much head-banging (not the good kind), this was my final solution, and I very much like it. It is flexible, simple to use, and allows very good control over class access. (The with reference only access is very useful.) If you use protected instead of private for the accessors/references, sub-classes of Foo can even return extended references from getReference. It also doesn't require any reflection, so it can be used in any environment.
I prefer delegation or composition or factory class (depending upon the issue that results in this problem) to avoid making it a public class.
If it is a "interface/implementation classes in different packages" problem, then I would use a public factory class that would in the same package as the impl package and prevent the exposure of the impl class.
If it is a "I hate to make this class/method public just to provide this functionality for some other class in a different package" problem, then I would use a public delegate class in the same package and expose only that part of the functionality needed by the "outsider" class.
Some of these decisions are driven by the target server classloading architecture (OSGi bundle, WAR/EAR, etc.), deployment and package naming conventions. For example, the above proposed solution, 'Friend Accessor' pattern is clever for normal java applications. I wonder if it gets tricky to implement it in OSGi due to the difference in classloading style.
I once saw a reflection based solution that did "friend checking" at runtime using reflection and checking the call stack to see if the class calling the method was permitted to do so. Being a runtime check, it has the obvious drawback.
As of Java 9, modules can be used to make this a non-issue in many cases.

Categories