We have a Shared Utilities project, two independent SDK projects (each referring to the Utilities) and some plugin projects, each using only one of those SDKs. Shared Utilities contains some all-static classes, which need to be made visible to the plugins mentioned, but we'd like to hide the rest of its classes from them.
How we can go about resolving the issue? We'd like to keep the build process as simple as possible (we're using Ant for the build) with least possible dependencies.
Here's the options we've considered so far and why we've discarded each approach:
Second Shared Utilities project, which will be made available to the plugins - will make deployment harder.
Build 2 separate .jar-s from the Shared Utils project, one containing only the all-static utilities and the other - whatever needs to be hidden. This would make the build more complex, i.e. additional dependencies to the plugins' build scripts.
Proxy all-static classes in each of the SDKs - duplicate method definitions, but the implementation simply calls the corresponding static method from the Shared project - seems most painless, downside is we'd need to copy the Javadoc by hand. Is there a simple Javadoc tag, which would do this automatically upon generation?
Convert all-static classes to "normal" and simply create subclasses in each SDK - unnecessary (to my mind) performance overhead.
"Exposing static methods through proxy classes"
I've read your complete question and I'm not sure what is your issue exactly.
Exposing static (non-instance related) method through a proxy (instance).
What you wan't to hide from what exactly. What you want to expose to what exactly.
public class A {
private A(){} //prevent instanciation
public static void doSomething(){} //want to expose to some class, hide from other
}
To limit exposition of doSomething you can set the visibility: Controlling Access to Members of a Class.
You can also remove the static nature and use a static factory pattern to return the object like:
public class A {
private A(){}
public void doSomething(){} //want to expose to some class, hide from other
//the new A can also be set in a member variable and
//return always the same instance, if it is unmuttable it will be thread safe.
public static A getInstance(){ return new A();}
}
This can look like the "same thing" but you can now control the visibility of all method in A by controlling only the visibility of the getInstance(), the javadoc stay on A, now to control exactly how the getInstance can be access... I would have to understand exactly what you want to do.
Related
I have a project with more than 100 java classes. My case is:
- i have Button.java, DropDown.java, Checkbox.Java, ListBox.java....
- also, some business class that represent a page for my web app with custom functions and mapping for Button.java and DropDown.java
- I want now to be able to use only functions from button and dropdown
An example:
public class FieldsProperties extends RHRegion{
public static void setProperties(String strMap){
HashMap<String, String> mapProperties = getMapProperties();
if(strMap.equals("Properties")){
mapProperties = UISummary.getProperties("UISummary");
}
setMapProperties(mapProperties);
RHRegion.setProperties(strMap);
}
}
so in my scenario i want to be allowed only functions from UISummary.java or just to be notified if it is used another class
You can use the IllegalType rule from checkStyle:
Checks that particular classes are never used as types in variable declarations, return values or parameters.
Rationale: Helps reduce coupling on concrete classes.
Simply add the classes to the list of illegalClassNames. You can configure checkStyle to treat the rule violation either as warning or as error.
Note that this does not prevent from instantiation - for example, assigning to a parent type is still possible. A better (or additional) rule might be IllegalInstantiation:
Checks for illegal instantiations where a factory method is preferred.
Assumed that you do not have a factory method for your restricted classes, this would violate all instantiations of classes defined in the classes property.
of that rule
There is also an IntelliJ plugin for checkstyle available.
Without having deeper knowledge of your application, but wouldn't it be much better to rethink your packge / application / class structure to prevent the usage of unwanted functionality?
I'm working on a project that consists of four parts:
The Main project that brings everything together. This contains the public static void main(String... args) entry point.
Component A
Component B
A 3rd party Common component that both A and B refer to.
I'm using Guice for the plumbing between all four parts, and this is my problem:
In both As and Bs main Guice modules I install a module that extends one that is defined in Common. At runtime this setup fails with the following error:
A binding to common.SomeClass was already configured at common.AbstractCommonModule.configure(). [source]
The reason for this is that I'm invoking common.AbstractCommonModule.configure() twice; once by installing a subclass instance of common.AbstractCommonPrivateModule from Component A's com.a.MainModule.configure(), and a second time from Component B's com.b.MainModule.configure().
Installing just one instance of common.AbstractCommonPrivateModule in Main is not an option, because AbstractCommonPrivateModule implements a specific binder method bindComplicatedStuff(ComplicatedStuff), for which I only know the argument inside A and B, respectively.
I tried working around this whole thing by wrapping A's and B's respective main Guice modules in PrivateModules. However, this failed with the next error:
Unable to create binding for %s. It was already configured on one or more child injectors or private modules %s%n If it was in a PrivateModule, did you forget to expose the binding? [source]
In my case, A's and B's respective main Guice modules are in fact ServletModules - which apparently I can install twice from Main.
How can I get around these errors and install the AbstractCommonPrivateModule module twice?
Edit: I uploaded some example code (with explanation about some details) to GitHub
Rather than having A and B install Common, have them requireBinding()'s for the classes they need from Common. Then modules that rely on A or B will need to also install Common. This may feel a little odd, but it's actually desirable, since A and B are now less tightly-coupled to Common.
Update
The reason I am installing two ShiroWebModules is because I want the Jersey resources in the ui module to only be secured using one Shiro configuration (one that unserstands password-protecting resources), while all Jersey resources in the api module should be be secured using an entirely different Shiro configuration (one that understands only bearer tokens as an authentication mechanism).
Broadly speaking, this is intractable. A Guice Injector provides one way of doing something (generally one implementation of an interface) to the whole application; not different mechanisms per package. Your two Modules, SwsApiServletModule and SwsUiServletModule provide a number of identical bindings, and SwsModule installs them both together. In essence you're saying "Guice, please provide a bearer-token-based authentication mechanism" then immediately after saying "Guice, please provide a password-based authentication mechanism". It can only do one or the other, so rather than picking one arbitrarily, it fails-fast.
Of course, there are a number of solutions, depending on what exactly your needs are. The most common is to use binding annotations and to have the UI and API code request different annotation. That way you can install two different implementations (with different annotations) of the same interface or class.
Here's an example:
package api;
public class ApiResources {
#Inject
public ApiResources(#ApiAuthMechanism AuthMechanism auth) {
this.auth = auth;
}
}
---
package api;
public class ApiModule implements Module {
public void configure() {
bind(AuthMechanism.class).annotatedWith(ApiAuthMechanism.class)
.to(BearerTokenAuthMechanism.class);
}
}
---
package ui;
public class UiResources {
#Inject
public UiResources(#UiAuthMechanism AuthMechanism auth) {
this.auth = auth;
}
}
---
package ui;
public class UiModule implements Module {
public void configure() {
bind(AuthMechanism.class).annotatedWith(UiAuthMechanism.class)
.to(PasswordAuthMechanism.class);
}
}
---
package webap;
public class WebappModule implements Module {
public void configure() {
// These modules can be installed together,
// because they don't install overlapping bindings
install(new ApiModule());
install(new UiModule());
}
}
You mention in a comment that you don't have control of the overlapping bindings being installed because they're coming from a third-party module. If that is the case (I didn't see where that was happening in your code) it's possible the third party doesn't want you doing what you're trying to do, for security reasons. For example,
simply binding the password-based mechanism might introduce vulnerabilities in the whole app. It might be worth trying to better understand how the third party intends for their modules to be used.
Another option, which isn't ideal but can work for some use cases, is to use two wholly separate Injector instances, one with each binding. Then you manually pass the instances you need to the UI and API code directly. This somewhat defeats the purpose of Guice, but it isn't always the wrong decision. Using child Injectors can make this less painful.
As an aside, your "sample code" is enormous, and probably more than 90% is unrelated to the problem. In the future please take the time to create an SSCCE that contains only the code relevant to the problem at hand. There's simply no way anyone's going to sift through 100+ Java files and 7,300+ lines of code to understand your problem. Not only will this make it easier for people who are trying to help you, but simply trying to create an SSCCE that demonstrates the problem will often be enough to help you understand and resolve it yourself.
To install the same module twice, override the .equals method in your module to refer to class rather than object equality. Guice won't install a module that is equal to one that has already been installed. This doesn't help much most of the time as you type:
install new AbstractCommonPrivateModule();
and so each object is a different instance which won't be equal to the last. Overriding the equals method gets around that:
#Override
public boolean equals(Object obj) {
return obj != null && this.getClass().equals(obj.getClass());
}
// Override hashCode as well.
#Override
public int hashCode() {
return this.getClass().hashCode();
}
However, note that this method is often incorrect.
Why not to do the above?
At this point, you're not really making use of Guice or dependency injection. Instead, you've tightly coupled the implementation of AbstractCommonPrivateModule with the implementation of B and C which install it. As mentioned by #dimo414, it seems like here the OP really wants to use two different ShiroWebModules, which is exactly what Guice is good at doing by installing those two different modules at a higher level. Likewise, higher level installs let you swap out while testing. If you actually want to swap one of the modules out at some point, Guice will again break.
This can also break if you override a module (which is another useful tool for testing).
The OP also wants to install a generic module twice. Wrapping another library's generic module adds additional risk; the original authors may have very good reasons for not implementing the above trick themselves, such as security.
I would like to test my java code with mockito and I would NOT like to have all my methods being public.
My problem is the following, let's assume I have the following code:
package com.whatever;
public class Parent
{
public void PlayWithChild(Child child)
{
child.Hug();
}
}
package com.whatever.subpackage;
public class Child
{
public void Hug()
{
}
}
and I have the test:
package com.whatever;
import com.whatever.subpackage;
public class Test
{
#Test
public void PlayWithChild_ChildHugged()
{
//Arrange
Child mckChild = Mockito.mock(Child.class);
//Act
new Parent(mckChild).PlayWithChild();
//Assert
Mockito.verify(mckChild).Hug();
}
}
Now if I make Hug method package-accessible (removing) the 'public', then I can not access it from the test... and I don't want to put everything (Parent, CHild, and my whole testable library) to the same package, I want to organize them.
You'll need to decide what degrees of encapsulation and abstraction you want your design to have. Java doesn't have a particularly granular way of specifying which components are accessible from which other components, so you may have to express those in documentation instead of relying on the compiler to enforce them for you.
In your case, I think you should make the Hug method public; if you want to make it really clear, add corresponding Javadoc or put Child into a subpackage called "internal" to discourage its casual use.
Java's four access levels:
public access, which poses no problem to testing or mocking
protected access, which includes package access and out-of-package subclasses. Testing within the same package is easy, but you may have to create manual test doubles to access/verify protected method calls from outside the package in question.
Default or package-private access, which as you noted is easy to test/call from within the same package. From other packages, the methods don't exist in any meaningful way for calling or testing.
private methods, which can't be called or tested directly.
Why would someone make a private method in test-driven development? Easy: Because the private method is an implementation detail that doesn't need to be tested. Likewise, protected or package-private methods are implementation details that don't need to be tested outside of the package. Here, if the Hug() method is public and it calls private or package-private method FeelBetter(), then callers from other packages should go only by the public API Hug without calling or concerning themselves with implementation details like FeelBetter().
The consequence of this is to almost encourage large, overscoped packages, because that may look to be the best way to hide irrelevant implementation details from other packages and to limit the number of entry points. It's true that putting close collaborators in the same package allows small package APIs, which is a good goal. With enough classes in one package, though, this notion breaks down; luckily, it only breaks down once the package is demonstrated to be so big it merits two separate packages, at which point you can stop and think about which components are connected and which ones can be extracted into APIs of their own. This may mean widening access for certain classes/methods from package to public, which is to be expected when splitting packages. It may also imply adding accessible getters or other state-querying methods for the sake of testing, which is also to be expected when developing testable components.
For more information about how to make testable systems, and how to interact with test doubles (or real tested components), I suggest reading Martin Fowler's article Mocks Aren't Stubs.
I am developing two Android applications with similar -- but not identical -- logic, and I want to share code between them. Currently, I have a project for each application, and an additional project for shared classes. The shared-classes project is a library, and the application projects are linked to this library.
The problem I have is with a class that's responsible for getting data from the server and caching that data. The class is called DataSingleton. Fetching the data has some logic which is the same for both applications, and some which is different. My question is how to design the class to support this.
There are some limitations here:
The data Singleton should be a singleton, as implied by its name.
Some of the shared logic in the shared project uses the DataSingleton, so the DataSingleton must also be in the shared-classes project (otherwise I get a build error).
I don't want to put the application-specific logic in the shared project.
If this was C++, I would have 2 different classes name DataSingleton -- one in each application -- and then have the linker connect the correct class. Both classes could inherit from some common base class, to handle the code sharing for shared logic. Can I do something similar in Java?
If it helps, I can "initialize" the DataSingleton at the start of the application with some argument that will determine its behavior. I thought about passing a class to it, but then that class doesn't have access to the DataSingleton's private members.
What is the "right" way to do this?
Think about singleton. It is a class that does 3 thigs:
1. it has a business logic
2. it creates instance of itself
4. it holds this single instance and provides access to it.
You want to hold more than one implementations of your class. This means that you need interface and/or abstract base class and several concrete classes. But in this case the best solution is to separate #1 from #2 and #3: create hierarchy of DataFetchers (I am sorry, I changed your name DataSingleton because it does not describe the reality any more) and DataFetcherAccessor:
interface DataFetcher {}
class DataFetcher1 implements DataFetcher{}
class DataFetcher2 implements DataFetcher{}
class DataFetcherAccessor<A extends DataFetcher> {
private static A accessor;
public static void setImpl(Class<A> c) {
accessor = c.newInstance();
}
public static A getAccessor() [
return accessor;
}
}
There are obviously a lot of other solutions. For example you can use SPI to locate available implementation of your interface. You can also scan your classpath yourself and discover available implementation of interface DataFetcher or use Reflections for this.
Strip the DataSingleton in the shared project of the parts that will need to change in the different projects, define it as an abstract class and change its name to AbstractDataSingleton or something like that, then just create 2 separate classes in each product called DataSingleton or whatever and make them extend the AbstractDataSingleton in the shared project.
I need to use two similar libraries one for one specific session of MVC. Means, they (their methods) won't be used simultaneously (I'll use If...Else around that specific session to choose methods of only one library at a time). The problem is:
For both libraries to work, its mandatory for my Entities (Model) to extend their classes (wished I was with C++).
They don't provide any Interface. So, I can't do multi-inheritance.
The only choice I have left: Create two different Models each for both libraries & use specific Model based on session (or being used libraries).
But, it'll duplicate the codes in Models. At this time there's no need to sync data between them due to use of persistent storage between MVC sessions. But still, duplicate code is a big headache to manage. Is there a way to avoid this?
You could create Adapters for each specific libraray. This would keep your own code clean from the other libraries.
Also you should consider using the Strategy Pattern for switching between both libraries. This becomes handy when the code becomes more complex and you can mock the libraries in tests.
You can't get around including both libraries if that's what you're asking. You could have a few options just depends on how you want things to work.
From what I understand, you could create two classes, each extending a different library, these classes implement an Interface, override any methods you need to.
Pseudo code:
private class Lib1Adapter extends Lib1 implements LibAdapter {
// wrapper methods call lib1 methods
}
private class Lib2Adapter extends Lib2 implements LibAdapter {
// wrapper methods call lib2 methods
}
public interface LibAdapter {
// method signatures for publicly accessible methods
}
public class YourModel {
public LibAdapter la = < boolean statement > ? new Lib1Adapter() : new Lib2Adapter();
}