Selecting Implementation of Interface based on the Parameter passed - java

I have a Parent interface.
public interface Parent{...}
And two classes that implement this interface.
public class ChildA implements Parent {...}
public class ChildB implements Parent {...}
Now I want to create an object of the child based on the parameter passed. Something like this,
Parent instance1 = Parent.getChild("Key1");
Currently, I am achieving this by using hashmaps.
static Map<String,Class<?>> map = new HashMap<String,Class<?>>();
static void init() throws ClassNotFoundException {
map.put("Key1",Class.forName("ChildA"));
map.put("Key2",Class.forName("ChildB"));
}
static Parent getChild(String key) throws InstantiationException, IllegalAccessException {
return (Parent) map.get(key).newInstance();
}
But the issue here is every time I implement a new child I will have to add it in the Parent init method. So is there any cleaner way to do this? Something like adding the information of the key to the child itself,
public class ChildA implements Parent {
private String key = "Key1";
...
So that when from the parent class I call getChild it refers to the respective Child.
Basically I am asking for a way to dynamically refer to a child of the parent based on the parameter passed.

You can use the service provider mechanism. This works best when actively using Java’s module system as then, the necessary parts are even integrated into the Java language.
The module containing the Parent interface must export its package, if implementations in other modules should be possible. Then, a module which wants to look up implementations of the interface must have a
uses yourpackage.Parent;
directive in its module-info. A module providing implementations must have a directive like
provides yourpackage.Parent with yourpackage.ChildA, yourpackage.ChildB;
in its module-info. It’s possible to use the interface and provide implementations within the same module. This might also be the module containing the declaration of the interface. In that case, it’s even possible to use the mechanism within a single module only and not to export the interface at all.
The compiler will already check that the specified implementation classes are public, have a public no-arg constructor, and truly implement the service interface. The implementations do not need to reside in an exported package; it’s possible that the interface is the only way to access an implementation from another module.
Since the compiler pre-checks the required invariants, you don’t need to deal with the issues inherent to Reflection. For example, you don’t need to declare or handle InstantiationException or IllegalAccessException.
A simple setup could be
module-info
module ExampleApp {
uses yourpackage.Parent;
provides yourpackage.Parent with yourpackage.ChildA, yourpackage.ChildB;
}
yourpackage/Parent
package yourpackage;
public interface Parent {
}
yourpackage/TheKey
package yourpackage;
import java.lang.annotation.*;
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface TheKey {
String value();
}
yourpackage/ChildA
package yourpackage;
#TheKey("Key1")
public class ChildA implements Parent {
}
yourpackage/ChildB
package yourpackage;
#TheKey("Key2")
public class ChildB implements Parent {
}
independentpackage/UsingTheInterfaces
package independentpackage;
import java.util.ServiceLoader;
import yourpackage.Parent;
import yourpackage.TheKey;
public class UsingTheInterfaces {
public static void main(String[] args) {
Parent p = getChild("Key1");
System.out.println(p);
}
static Parent getChild(String key) {
return ServiceLoader.load(Parent.class).stream()
.filter(p -> {
TheKey keyAnno = p.type().getAnnotation(TheKey.class);
return keyAnno != null && keyAnno.value().equals(key);
})
.findAny()
.map(ServiceLoader.Provider::get)
.orElse(null); // decide how to handle absent keys
}
}
As said, when you have an exports yourpackage; directive, implementations can be provided by other modules and the ServiceLoader will discover those implementations dynamically for all modules present at runtime. The using module does not need to know them at compile time.
There is a predecessor mechanism for older Java versions not having a module system, which is also handled by ServiceLoader in a backwards compatible manner. Those providers have to be packaged in a jar file containing a file META-INF/services/yourpackage.Parent containing a list of all classes within the jar file implementing the interface. Before Java 9, the ServiceLoader also lacks the Stream API support that allowed to query the annotations before instantiating the implementation. You can only use the Iterator that will already instantiate the classes and return an instance.
One way to avoid unnecessary overhead with the old API, is to split the interface into a service provider interface and an actual service interface. The provider interface will supply meta information and act as a factory for actual service implementations. Compare with the relationship between CharsetProvider and Charset or FileSystemProvider and FileSystem. These examples also demonstrate that the service provider mechanism is already widely used. More examples can be found in the java.base module documentation.
This was just an overview; the API documentation of ServiceLoader contains more details about the mechanism.

Option 1: I suggest you to use a simple factory class like this one:
public class ChildFactory {
public static Parent getChild(String key) throws ClassNotFoundException {
if (key.equals("Key1"))
return new ChildA();
if (key.equals("key2"))
return new ChildB();
throw new ClassNotFoundException();
}
}
These are the reasons:
Simple and easy to extend: the class does only one thing, create objects
Don't use the deprecated newInstance()
Clean the interface Parent from static "factory" methods
Option 2: define a function that given the key it returns the class name and use it to create the instance:
public class ChildFactory {
public static Parent getChild(String key) {
String className = childClassNameFor(key);
return (Parent) Class.forName("my.package."+className).newInstance();
}
private static String childClassNameFor(String key) {
return "Child" + key;
}
}
And then you can use it like this:
Parent p = ChildFactory.getChild("A");

Related

How can i restrict my clients with selected methods from the class?

Let's say I have 1 complete class with around 20 methods which provide different functionalities.
Now we have multiple clients using this class, but we want them to have restricted access.
For e.g. -
Client 1 - Gets access to method1/m3/m5/m7/m9/m11
Client 2 - Gets access to method2/m4/m6/m8/m10/m12
Is there any way I can restrict this access?
One solution which I thought:
Create 2 new classes extending Parent class and override methods which are not accessible and throw Exception from them.
But then if 3rd client with different requirement, we have to create new subclass for them.
Is there any other way to do this?
Create 2 new classes extending Parent class and override methods which
are not accessible and throw Exception from them. But then if 3rd
client with different requirement, we have to create new subclass for
them.
It is a bad solution because it violates Polymorphism and the Liskov Substitution Principle. This way will make your code less clear.
At first, you should think about your class, are you sure that it isn't overloaded by methods? Are you sure that all of those methods relate to one abstraction? Perhaps, there is a sense to separate methods to different abstractions and classes?
If there is a point in the existence of those methods in the class then you should use different interfaces to different clients. For example, you can make two interfaces for each client
interface InterfaceForClient1 {
public void m1();
public void m3();
public void m5();
public void m7();
public void m9();
public void m11();
}
interface InterfaceForClient2 {
public void m2();
public void m4();
public void m6();
public void m8();
public void m10();
public void m12();
}
And implement them in your class
class MyClass implements InterfaceForClient1, InterfaceForClient2 {
}
After it, clients must use those interfaces instead of the concrete implementation of the class to implement own logic.
You can create an Interface1 which defines methods only for Client1, and an Interface2 which defines methods only for Client2. Then, your class implements Interface1 and Interface2.
When you declare Client1 you can do something like: Interface1 client1.
With this approach, client1 can accesses only methods of this interface.
I hope this will help you.
The other answers already present the idiomatic approach. Another idea is a dynamic proxy decorating the API with an access check.
In essence, you generate a proxy API that has additional checks on method calls to implement a form of Access Control.
Example Implementation:
package com.example;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
#FunctionalInterface
public interface ACL<P, Q> {
boolean allowed(P accessor, Q target, Method method, Object[] args);
class ACLException extends RuntimeException {
ACLException(String message) {
super(message);
}
}
#SuppressWarnings("unchecked")
default Q protect(P accessor, Q delegate, Class<Q> dType) {
if (!dType.isInterface()) {
throw new IllegalArgumentException("Delegate type must be an Interface type");
}
final InvocationHandler handler = (proxy, method, args) -> {
if (allowed(accessor, delegate, method, args)) {
try {
return method.invoke(delegate, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
} else {
throw new ACLException("Access denies as per ACL");
}
};
return (Q) Proxy.newProxyInstance(dType.getClassLoader(), new Class[]{dType}, handler);
}
}
Example Usage:
package com.example;
import java.lang.reflect.Method;
public class Main {
interface API {
void doAlpha(int arg);
void doBeta(String arg);
void doGamma(Object arg);
}
static class MyAPI implements API {
#Override
public void doAlpha(int arg) {
System.out.println("Alpha");
}
#Override
public void doBeta(String arg) {
System.out.println("Beta");
}
#Override
public void doGamma(Object arg) {
System.out.println("Gamma");
}
}
static class AlphaClient {
void use(API api) {
api.doAlpha(100);
api.doBeta("100");
api.doGamma(this);
}
}
public static class MyACL implements ACL<AlphaClient, API> {
#Override
public boolean allowed(AlphaClient accessor, API target, Method method, Object[] args) {
final String callerName = accessor.getClass().getName().toLowerCase();
final String methodName = method.getName().toLowerCase().replace("do", "");
return callerName.contains(methodName);
}
}
public static void main(String[] args) {
final MyACL acl = new MyACL();
final API api = new MyAPI();
final AlphaClient client = new AlphaClient();
final API guardedAPI = acl.protect(client, api, API.class);
client.use(guardedAPI);
}
}
Notes:
The accessor does not have to be the client object itself, it can be a string key or token that helps ACL identify the client.
The ACL implementation here is rudimentary, more interesting ones could be One that reads ACL from some file or One that uses method and client annotations as rules.
If you don't want to define an interface for API class, consider a tool like javassist to directly proxy a class.
Consider other popular Aspect Oriented Programming solutions
You should create one super class with all the methods and then provide Client specific implementations in their corresponding sub classes extending from the super class defined earlier.
If there are methods which are common implementation for all clients, leave their implementations to the super class.
It seems like you are a bit confused about the purpose of Classes and Interfaces. As far as I know, an Interface is a contract defining which functionality a piece of software provides. This is from official java tutorial:
There are a number of situations in software engineering when it is
important for disparate groups of programmers to agree to a "contract"
that spells out how their software interacts. Each group should be
able to write their code without any knowledge of how the other
group's code is written. Generally speaking, interfaces are such
contracts.
Then you can write a Class which implements this Interface/contract, that is, provides the code that actually perform what was specified. The List interface and the ArrayList class are both an example of this.
Interfaces and Classes have access modifiers, but they aren't designed to specify permissions to specific clients. They specify what is visible for other piece of software depending the location where it is defined: Class, Package, Subclass, World. For example, a private method can be accessed only inside the class where it is defined.
From official Java tutorial again:
Access level modifiers determine whether other classes can use a
particular field or invoke a particular method. There are two levels
of access control:
At the top level—public, or package-private (no explicit modifier).
At the member level—public, private, protected, or package-private (no
explicit modifier).
Maybe you want something more powerful like Access Control List (ACL).
Your question is a little unclear, leading to different possible answers. I'll try to cover some of the possible areas:
Object encapsulation
If your goal is to provide interfaces to different clients that only provide certain functionality or a specific view there are several solutions. Which matches best depends on the purpose of your class:
Refactoring
The question somehow suggests that your class is responsible for different tasks. That might be an indicator, that you could tear it apart into distinct classes that provide the different interfaces.
Original
class AllInOne {
A m1() {}
B m2() {}
C m3() {}
}
client1.useClass(allInOneInstance);
client2.useClass(allInOneInstance);
client3.useClass(allInOneInstance);
Derived
class One {
A m1() {}
}
class Two {
B m2() {}
}
class Three {
C m3() {}
}
client1.useClass(oneInstance);
client2.useClass(twoInstance);
client3.useClass(threeInstance);
Interfaces
If you choose to keep the class together (there might be good reasons for it), you could have the class implement interfaces that model the view required by different clients. By passing instances of the appropriate interface to the clients they will not see the full class interface:
Example
class AllInOne implements I1, I2, I3 {
...
}
interface I1 {
A m1();
}
But be aware that clients will still be able to cast to the full class like ((AllInOne) i1Instance).m2().
Inheritance
This was already outline in other answers. I'll therefore skip this here. I don't think this is a good solution as it might easily break in a lot of scenarios.
Delegation
If casting is a risk to you, you can create classes that only offer the desired interface and delegate to the actual implementation:
Example
class Delegate1 {
private AllInOne allInOne;
public A m1() {
return allInOne.m1();
}
}
Implementing this can be done in various ways and depends on your environment like explicit classes, dynamic proxies , code generation, ...
Framework
If you are using an Application Framework like Spring you might be able to use functionality from this Framework.
Aspects
AOP allows you to intercept method calls and therefor apply some access control logic there.
Security
Please note that all of the above solutions will not give you actual security. Using casts, reflection or other techniques will still allow clients to obtain access to the full functionality.
If you require stronger access limitations there are techniques that I will just briefly outline as they might depend on your environment and are more complex.
Class Loader
Using different class loaders you can make sure that parts of your code have no access to class definitions outsider their scope (used e.g. in tomcat to isolate different deployments).
SecurityManager
Java offers possibilities to implement your own SecurityManager this offers ways to add some extra level of access checking.
Custom build Security
Of course you can add your own access checking logic. Yet I don't think this will be a viable solution for in JVM method access.

Java - get information into library project from project which includes this library

I am developing a library which needs some configuration information from project which would include this library. What I was thinking is to having some abstract methods in my library and force application to implement these methods.
What I am looking for is:
Class A in library having some static abstract methods, say
having a method named getURL();
A class B implements these static
methods in actual application and implement method getURL() from
class A.
In my library, I called A.getURL(), it should call method
implementation from class B which extends class A and should return me the url.
But an abstract method can't be static in Java. Is there some workaround to achieve same like functionality.
public abstract class A {
protected static A INSTANCE;
public static String getURL() {
return INSTANCE.getURL();
}
protected abstract String getURL0();
}
class B extends A {
static {
INSTANCE = new B();
}
#Override
protected String getURL0() {
return "application-specific url";
}
}
A static abstract method makes no sense, since the notion that an abstract method should be implemented by an extending class (which is part of OO), and static denotes a non instance method (not OO).
But I had a similar problem in a J2EE project recently, in which the library needed some specific configuration depending on the project that used it.
What we decided to do is to have a configuration file with a specific name in the project, that the library should read as soon as loaded. If the file and/or the required configurations were not found, an exception is thrown (you can create your own).
I think this way you can decouple implementation of the library from the projects using it.
Based on your answers to questions I would recommend the following:
Define an interface for a class that retrieves the properties like so:
interface LibaryDetails {
URL getURL();
String getName();
}
Then create a Factory method of some kind which causes your Library to run and do it's thing. Refactor your code out of the main so it can be accessed from here. Have this method take the interface as a parameter:
public class LibraryFactory{
public static void startLibrary(LibaryDetails details){
URL url = details.getURL();
String name = details.getName();
// start Library things
}
}
Now your Library only needs to expose the interface and the static Factory. Your Applications just needs to pass it's implementation of the LibraryDetails interface to the factory method and your library can access the information.

How to implement the API/SPI Pattern in Java?

I am creating a framework that exposes an API for developers to use:
public interface MyAPI {
public void doSomeStuff();
public int getWidgets(boolean hasRun);
}
All the developers should have to do is code their projects against these API methods. I also want them to be able to place different "drivers"/"API bindings" on the runtime classpath (the same way JDBC or SLF4J work) and have the API method calls (doSomeStuff(), etc.) operate on different 3rd party resources (files, servers, whatever). Thus the same code and API calls will map to operations on different resources depending on what driver/binding the runtime classpath sees (i.e. myapi-ftp, myapi-ssh, myapi-teleportation).
How do I write (and package) an SPI that allows for such runtime binding, and then maps MyAPI calls to the correct (concrete) implementation? In other words, if myapi-ftp allows you to getWidgets(boolean) from an FTP server, how would I could this up (to make use of both the API and SPI)?
Bonus points for concrete, working Java code example! Thanks in advance!
Take a look at the java.util.ServiceLoader class.
In general, the idea is this:
API Jar
Supply the interface
Use the ServiceLoader class to lookup the implementation
Binding/Driver Jar
Implement the interface
Create the file META-INF/ and specify the classname that implements it
There's a good example right in the javadocs:
http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
API Jar
package com.foo;
public interface FooInterface { ... }
public class FooInterfaceFactory {
public static FooInterface newFooInstance() {
ServiceLoader<FooInterface> loader = ServiceLoader.load(FooInterface.class);
Iterator<FooInterface> it = loader.iterator();
// pick one of the provided implementations and return it.
}
Binding Jar
package com.myfoo;
public class MyFooImpl implements FooInterface { ... }
META-INF/com.foo.FooInterface
com.myfoo.MyFooImpl
EDIT
SPI Example
public interface FooSpi {
void accepts(String url);
FooInterface getFooInstance();
}
public class FooInterfaceFactory {
public static FooInterface getFooInterfaceInstance(String url) {
ServiceLoader<FooSpi> loader = ServiceLoader.load(FooSpi.class);
Iterator<FooSpi> it = loader.iterator();
while (it.hasNext()) {
FooSpi fooSpi = it.next();
if (fooSpi .accepts(url)) {
return fooSpi.getFooInstance();
}
}
return null;
}
}
And of course, change the filename to com.foo.FooSpi and provide an implementation of FooSpi. That will allow you to segregate the public API from the Spi interface.
If you want to hide the accepts method, you could always have a second interface which is your public API, and t
Well you know that API are what clients use, and SPI is what your library use internally.
You shall have classes which implement your API classes, which depend on SPI interfaces, and have some implementations for your SPI.
Most of the time SPI interfaces contain low level methods (abstraction for direct working with FTP, SSH and... in your example), and your library provides higher level operations for your clients.
Maybe your SPI interfaces would be such as:
public interface ProtocolSPI {
boolean isCompatibleWithUrl(String url);
Handle connect(String url, Map<String, Object> parameters);
int readData(Handle handle, byte[] bytes);
void writeData(Handle handle, byte[] bytes, int startIndex, int length);
void closeHandle(Handle handle);
}
and you have code which depends on this interface for working with replaceable part.
You may have a ProtocolSPIFactory which uses java.util.ServiceLoader to find available implementations of your ProtocolSPI (in the class-path), then instantiates them and by calling isCompatibleWithUrl finds out which implementation to use for a specific url.

What is the right way to organize Jersey resources using inheritance and generics?

I'm developing an app with Jersey where I have many resources. Although main functionality of these resources varies, they share lots of common methods (like list, read, update and etc). The app runs on Google App Engine and uses Guice for dependency injection.
My first approach was to have a generic AbstactResource which contains all common logic, and it's respectively extended by all other resources which add their required custom methods.
public class AbstractResource<T> {
#GET
public ListPage<T> list(#QueryParam("limit") Integer limit,
#QueryParam("start") Integer start) {
// ... implementation
}
#GET
#Path("/{id}")
public T get(#PathParam("id") Long id) {
// ... implementation
}
And sample resource looks like:
public class TenantResource extends AbstractResource<Tenant> {
// custom resource related methods here
}
Everything works fine in this case. The problems appear when I add one more level of abstraction. Let's say if I want to store history and changelogs only for some of my resources. I've created one more abstract class extending AbstractResource called AudiatableResource which adds the required functionality.
public abstract class AuditableResource<T extends AuditableModel>
extends AbstractResource {
// here I override update and create methods to save changelogs
}
As you see the type parameter in this case has changed (now it extends AuditableModel).
New concrete resources will look like:
public class PropertyResource extends AuditableResource<Tenant> {
// custom resource related methods here
}
In this case everything still works, but this time I'm getting lots of warning messages on start-up:
WARNING: Return type T of method public T com.pkg.AbstractResource.get(java.lang.Long) is not resolvable to a concrete type
WARNING: Return type T of method public T com.pkg.AbstractResource.getNew() is not resolvable to a concrete type
WARNING: Return type com.pkg.data.ListPage<T> of method public com.pkg.ListPage<T> com.pkg.AbstractResource.list(java.lang.Integer,java.lang.Integer) is not resolvable to a concrete type
I really wonder if this approach is correct using Jersey and if I can just ignore this messages. It would be interesting to know how resources are organized in cases when there are large number of them.
One way to go is to separate the definition of the resources from the implementation.
Have very simple resource classes, defining the different services you want to offer. This way, the API you expose through rest is easily located and audited. The different methods are probably delegates to an implementation class
Implement the business logic of your resources in the implementations, where you might want to use inheritance to factor common behavior.
The reason you get those messages at runtime is that jersey uses runtime information about types in the resource. Generic type information being erased at compile time, it cannot get the actual return type of the generic class methods. If you provide a REST "facade" to your implementation, you can make this explicit.
public class Facade {
private final PropertyResource propertyResource;
public Facade() {
propertyResource = new PropertyResource();
}
#GET
#Path("somepath")
public Tenant something() {
return propertyResource.something();
}
}

How to inject package private classes using Guice

Firstly i like what Guice does however i have also like to make as few classes in my system public. All services in my system are package private w/ only the interface public. This presents a few problems for Guice if one does not use a provider. I would prefer some alternative that allows me to provide a strategy to do the following:
for component C
requires dependencies X, Y, Z
call this method w/ X, Y, Z to create instance.
.. repeat again for all components.
In step 2 of the above psuedo code Guice now scans for #inject annotations. If this strategy was available I could decide how id like to find my component's dependencies in a generic way.
Unfortunately Module.bind just doesnt work because it works w/ classes literals.
The strategy interface for the above might look like this
interface ComponentDiscoverer {
Set<ComponentDefinition> components();
}
interface ComponentDefinition<T> {
List<RequiredDependency> requiredDependencies(); // similar to Guice's Key
<T> create( List<SatisfiedDependency> dependencies ); // factory method.
}
Guice gets all components by calling a registered ComponentDiscoverer.
It then calls the registered ComponentDiscoverer.components();
For each ComponentDefinition.requiredDependencies()
on demand call ComponentDefinition.create
Is this any built into Guice way or third party library to achieve the above ?
SAMPLE
package companyX;
public interface Service {
void execute();
}
package companyX;
package private class ServiceImpl implements Service {
static ServiceImpl create( Dependency dependency){
return new ServiceImpl( dependency );
}
private ServiceImpl( Dependency dependency ){
}
void execute();
}
package companyX;
package private class ServiceImpl2 implements Service2{
}
package companyX;
public class Factory {
Service alpha( Dependency ){
return ServiceImpl.create( dependency );
}
Service beta( DifferentDependency ){
// boring left out
}
Service2 gamma( AnotherDifferentDependency);
}
My module lives in a different package and all creation goes thru Fatory because everything else is package private.
You shouldn't have just one Module unless your application is very simple. You should have a module for each package that you have package-private classes you want to use in. This allows you to bind those package-private classes to the public interfaces. This is a standard practice for using Guice, and it's mentioned in the Keep Constructors Hidden section of the documentation.
With a module in the package, you just need normal #Injectable constructors or provider methods:
#Provides #Alpha Service alpha(Dependency dependency) {
return ServiceImpl.create(dependency);
}

Categories

Resources