Easily switching between two different implementations of a java library? - java

I am currently working on a project that uses a third party library to manage hardware.
I wish to create a substitute library that presents the same interface, but instead of controlling actual hardware just presents a nice fake GUI. Preferably this can be done just by replacing the jar.
The problem is that all of the third party code is in the namespace edu.edu.wpi.first.wpilibj, and of course the namespace for my library is going to be very different.
Is there any way of easily switching implementations between the two libraries providing the same interface in java?

Yes, there are design patterns to do that.
You can look into Strategy pattern.
Even better you can look into Dependency injection.
You can use Google Guice as container and based on your configuration, at runtime, your implementation can switch between using N libraries.
At the end of the day, you need to wrap those libraries around some abstraction.
here is an example:
interface ISomeOperation{
void process();
}
class ThatUsesTheWPILIBJ implements ISomeOperation{
void process(){
//use library here
}
}
class ThatUsesYourMock implements ISomeOperation{
void process(){
//use your mock here
}
}
public YourUIClass{
private ISomeOperation _operatingClass;
public YourUIClass(ISomeOperation operatingClass){
_operatingClass = operatingClass;
}
public void render(){
_operatingClass.process();
}
}
Now all you need to do is wiring. Look at google guice configuraion.

Yes. ServiceLoader.
It allows to switch implementations by puting jar in classpath (or by some configuration).
But it does not help with existing code. (But once done, switching to any other implementation is easy.
Its easy to library that uses it, but if library does not use it, it can be hard to introduce service loading. You would need to create service-loading wrapper. And if another library uses the original library, you would need to change and recompile it too.
Another approach would be puting it in same package as original library and mirror its public interface. But that is ugly.

Related

What do i do if need to change a libraries functionality

I have a class in a Java Library(open-m3u) that I need to change just slightly.
The functionality is easy to implement on my own without using the library. The library is open-source so i have access to all of its code. The class is made in such a way that inheriting it or even changing that small part is not possible. My question is should I copy that class and all the classes that it depends on and put them in my own code base and change the functionality or should implement the functionality myself. Or is there another option?
The functionality is easy to implement on my own without using the
library.
IMHO, then that's the way to go. Your other options are:
Build the functionality around the library: you say that's not possible in your case.
Create a branch of the library in your own source control system. That means you'll have to keep that repository in sync with the library maintainers, which means a permanent burden. And you have to check what the library's license says about forking.
Copy the relevant parts into your code base and do the modifications there. Then you won't profit from future enhancements or bug fixes, but still have to maintain code that was created and architected by someone else, and doesn't exactly fit your requirements. And you have to check what the library's license says about copying parts into a foreign code base.
They all have their drawbacks.
As a general remark: in 25 years of professional software development, I've seen both successful usages of external libraries as well as complete failures. Some times, we invested more time into evaluating existing libraries (and then finding out that nothing matched) than we needed for implementing the project-specific solution on our own.
And every library you can do without, makes config management and rollout easier.
Decorator pattern allows you to add new functionality to existing object.
If java library you use has any class like this:
public class LibraryClass implement ILibraryInterface {
public void someMethod() {
...
}
}
Then you can create Decorator class:
public class LibraryClassDecorator implement ILibraryInterface {
private LibraryClass libObj;
public LibraryClassDecorator(LibraryClass libObj) {
this.libObj = libObj;
}
public void someMethod() {
libObj.someMethod();
// here you can do whatever you want.
// Add some additional logic
// transform result value if there is some
}
}
Note: you have to implement the same interface to follow Liskov substitution principle
A solution will be to make a class that extends the one you wanna change and overide the part you wanna change

importing a library as a package private

I know we can create a package private class in java. So the class is Internal and only accessible in the specified module:
class MyPackagePrivateClass
{
...
}
Now I am developing an android library which i named LibraryA and I wish to use an existing LibraryB in my own LibraryA. How is it possible to prevent user of LibraryA from using the LibraryB directly?
Is there any concept like package private library or anything like that?
Update (For those who ask 'why do I need this?')
In LibraryB there are methods like this:
public QueryBuilder select(String... columns);
But I strongly am of the view that we should use Type-Safe Enum pattern and prevent users from passing strings to these methods(Considering maintenance and refactoring issues). So I decided to wrap those methods in LibraryA:
public TypedQueryBuilder select(Column... columns) {
queryBuilder = queryBuilder.select(toString(columns));
return this;
}
Therefore users of my library should use the Typed methods I provided (Column is a type safe enum here). But if they have access to the original method they may use those instead and I tend to forbid this.
In Java, with polymorphism, you can't hide a public method of an extended class.
I think that you could archive your goal with Facade Pattern: hide all the complex logic and, in this case, control the access and, if needed, implements some interfaces.
Jigsaw project tries to reach the same goal. But it can take long enough to wait until it would be ported to Android. Until then the best solution IMO is to use package private methods. User will be able to understand that he shouldn't use these methods.
Anyway it's impossible to ultimately forbid library user to do certain things, because one can use reflection or substitute class to get rid of nasty restrictions. But it's possible to encourage user not to do certain things - that's what can be done.
Make a jar file out of library B and import it in library A.
https://stackoverflow.com/a/1051705/6897626

Using shared class libraries internally, but not providing access to them in released SDK

After some research I cannot come across the best approach for this. There will be certain color classes that I would like to share amongst multiple projects. Let's call one of them EncryptedColor. Since it is used across multiple projects I don't want multiple copies of it in existence of course. Otherwise I would need to make sure that an update in one location would need to be updated everywhere. However, these classes are needed in some released SDKs that we provide to customers.
How could I design it such that I can use these classes but not provide them with the classes that they don't need access to from their SDK. I don't want useless classes to become visible and flood the smaller subset of classes that they really need to be seeing.
A couple approaches I have thought of so far but aren't quite ideal:
Try and use a doclet structure that hides the calls within the javadoc such as doclava. Javadoc has not fully implemented its own hiding mechanism yet. As I understand this doesn't keep the functions from being visible, but it was mentioned in one spot that you would need reflection to use the calls. I don't see how just the javadoc does that so I must have been missing something.
Android has designed themselves it seems to force reflection from some #hide attributes included in methods that they have in source code. But from the sounds of it, the system hides those and then uses a different jar when it is loading to make those visible at launch time. Probably not useful here.
If I were to keep shared classes in the same package name I could access default and protected members, but...then I am keeping all my classes that use these in the same package name. Not quite ideal either, but it could be done in that manner if I needed to. Might get out of hand with large quantities of shared resources.
What approaches are taken typically in situations such as these? I haven't liked my findings and thought process thus far.
Short answer : you can't hide/remove these classes as they are needed at runtime by your application.
In my opinon, you have 3 alternatives :
Change the classes access to "package private". Yes, doing that doesn't make it impossible to access them, but these classes won't be accessible directly.
Remove the classes and create an API. You want to hide the logic ? Remove it and provide it through a REST API for instance. Depending or your architecture, it could be difficult or impossible.
Create all the instance of these classes in a dynamic way, with Class.forName, using Spring or as in #Steve K answer, with Java's ServiceLoader. As a result, you will be able to remove these classes from the main jar and make them more private, in a way. Again, classes will be here but a little less accessible.
My suggestion that could work would be to implement your color classes as a service using the Java ServiceLoader
You make an interface for your color classes, and implementations can be called using the ServiceLoader class. Then you simply separate your color classes into two packages - a public package you can jar up and distribute with your SDK, and a private package for those classes you want to be internal. The ServiceLoader will find all the color classes available so long as the jar files are in your project's classpath.
For example, if your color classes (as an example) had a common interface like this:
public interface MyAppColor {
public int getRed();
public int getGreen();
public int getBlue();
public int getAlpha();
public void setRed(int red);
public void setGreen(int green);
public void setBlue(int blue);
public void setAlpha(int alpha);
public boolean isValid();
public void doSomething(Object arg);
}
Then you could have a bunch of implementing classes in a jar file, with a service descriptor file included in the jar at the path:
META-INF/services/com.my.app.MyAppColor
The text of that file is simply the list of classes in the jar that implement the interface - one per line:
com.my.app.MyPublicAppColor
com.my.app.MyEncryptedPublicAppColor
com.my.app.MyOtherPublicAppColor
etc. Then all you have to do is make a factory for instantiating the correct type, which could be as simple as this:
public class MyAppColorFactory {
private static ServiceLoader<MyAppColor> serviceLoader = ServiceLoader.load(MyAppColor.class, null);
public static MyAppColor get(String className){
if (className != null){
for (MyAppColor c : serviceLoader){
if (className.equals(c.getClass().getName())){
return c;
}
}
}
return null;
}
}
Deploying only needed code:
- Use Only The Needed Source In Development (1) (2)
Since you have an entire library and many deployments which each use different components, the easiest way to do what you suggest is to use only the sources that you need; not a single library. You can ignore the unused sources. This will only ship the needed code.
- Make The Library "Package Private"
This will allow the access only for the public components of the library and everything else will not be callable. But, it will still ship all the code.
- Create an API as a REST SDK
This will require web access, not desirable for performance code {any code really}. You will ship no sdk code with this method.
- Obfuscate the code
Easy with the correct tools. Obfuscation will change the class and method names in production code to gibberish. This will make the library basically unusable to anyone but you. This will ship all the code but it will be obfuscated
- Native API
You can compile java to machine code and use it in production or as the api. You can also create the api in a native language {not desirable}.

Best practice to hide a service implementation

I want to hide the implementation (concrete class) of a service (interface) from the API user. The implementation is provided to the user by a factory which uses the Java API ServiceLoader mechanism. This Loader requires the implementation class to have public visibility. This is OK as long as the implementation is hidden in a different JAR (apart from the API JAR) the user is not directly depending on.
However, for easy distribution the content of the JAR with the default implementation is packed into the API JAR. So effectively the user depends on this prepacked JAR where the default implementation class is available with public visibility. Nothing keeps people from directly instantiating the implementation. I don't want that to be possible.
My bad ideas:
implement an own version of ServiceLoader which allows to load package private implementations (btw, why does the Java API ServiceLoader doesn't allow this?)
ship separate API and implementation JARs
What do you think is the right way? Any compromise?
Using OSGi or other heavy machinery is out of question.
Disappointing maybe but:
Make a separate jar and put that with the other third party jars.
Let the installer/the deployment process handle nice packaging of all.
Do not make this jar available during compile time; maven: <scope>runtime</scope>.
The only other way would be the have #Deprecated in the javadoc, with as comment how to use the corresponding class using the java service API.
In C# you can create an internal interface that is visible only to relevant friend assemblies, and then explicitly implement the interface. I'm not sure how you would do this in Java, but conceptually this is how I've been able to work around this problem in the .NET world.
EDIT I just looked it up, from what I can tell Java doesn't have explicit implementation for interfaces. As an FYI, an explicit implementation of an interface requires you to make a function call through an interface member, you can't call it as a member of the implementing class. This is why my technique works for me, at least in the .NET world.
Alternatively, I would suggest putting the interface in another JAR, and don't distribute it with the API
You can't easily prevent people from instantiating/accessing any shipped class.
As such I would perhaps simply wrap the ServiceLoader mechanism that you're using and provide the instantiated class referenced through a Java interface (rather than as a concrete implementation reference).
I prefer your first approach, making the implementation class package private, and using a ServiceLoctor to retrieve a specific service. In my project, the package structure is like this:
-package
|-ServiceInterface(public)
|-ServiceImplementation(default,package private)
|-ServiceLocator(public)
The serviceLocator is like this:
public class ServiceLocator{
private static final Map<String,Service> services;
static {
services=new HashMap<String,Service>();
services.put("default",new ServiceImplementation());//hide implementation
}
public Service getService(String name){
return services.get(name);
}
public registerService(Service service, String name){
services.put(name,service)
}
}
The end user does not have access to the implementation class, and in later time, you can easily change to use a different implementation class.

Java - Use annotations and intercept methods?

Is there a simple way to intercept methods in java. I need to add an annotation to required methods so that a piece of logic gets called before going through the method.
public void verifyActivity() {
// Asset if you are on a wrong page
}
#VerifyActivity
public void testLogin() {
// Login for my automate test
}
#VerifyActivity
public void testSomethingElse() {
// Test some other UI Automation stuff
}
EDIT:
The recommended guice library for android apps does not contain AOP.
Is it possible to achieve this using reflection without adding any libraries?
Guice provides easy way of implementing annotations. Check this out.
http://code.google.com/p/google-guice/wiki/AOP
http://code.google.com/p/google-guice/
As sid malani said Google Guice is great for this. In general you want to read up on aspect oriented programming tutorials ... There is a nice tool called JMangler that may be of use as well
You can use reflection if you've coded to interfaces through dynamic proxies.
I doubt that it can be nicely done without any 3rd party libs.
There is a library called cglib, which is capable of such things.
Basically it will create a subclass of the intercepted class at runtime. You'll be able to "override" methods by implementing an InvocationHandler, which will act as a proxy when any of the superclass methods being called.

Categories

Resources