I have an interface method in a library which is being called by a method in the same library. The implementations are in the applications which include the library. The implementations are different for every application. In order to call the interface method, the calling method must instantiate the interface with its implemented class. But since the calling method is in the library, it has no access to the classes in the applications. The calling method is started by a background service and not by the application.
The interface in the library:
public interface InterfaceA {
void methodA();
}
The class in the application which implements the interface:
public class ClassA implements InterfaceA {
#Override
public void methodA() {
// do something
}
}
The method in the library which calls the interface method:
public void callInterface() {
InterfaceA ia;
ia.methodA(); // how to get this to work?
}
How do I call the interface method from the library without any access to the interface implementations in the applications? I cannot instantiate the interface from my library as the implementation classes are in the application which the library has no access to.
You don't need to do anything to get it to work if you have an instance of the interface:
public void callInterface(InterfaceA ia) {
ia.methodA();
}
And then add this parameter to the library methods which call this method, and so on. When applications call this method, they can pass their implementations.
Or if you really need to instantiate the interface inside the method, add another interface:
public void callInterface(Supplier<InterfaceA> iaSupplier) {
InterfaceA ia = iaSupplier.get();
ia.methodA();
}
See https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html.
The calling method is started by a background service and not by the application.
And what starts the background service? You need to add some way for the application to pass the implementation to it.
Alternately, you could use SPI (https://docs.oracle.com/javase/tutorial/ext/basics/spi.html) but it may be overkill.
public void callInterface() {
InterfaceA ia;
ia.methodA(); // how to get this to work?
}
Above should result in compilation problem.
The library function should take as parameter the Interface InterfaceA in method as shown in another answer Or If it is a stateless implementation then pass it while using the Class that contain this method.
Related
In android IPC using binder, when we create an aidl file, build will automatically generate a stub class extending binder and override all the aidl methods right?.
In the service class implementation for the aidl methods , have seen instantiating the stub class generated instead of extending the stub class.Since stub class is abstract , how can it be instantiated?
The question was generic related to interface instantiation. As we know interface can not be instantiated but code like below:
interface in = new in() {
public void test(){
return "ok";
}
}
is possible as I am defining what the instance need to be done.
I was wondering if it was possible to only allow a certain set of classes to execute a function.
I have a method: setPermission()
This method should only be called by certain classes throughout the project.
Some people suggested having the calling class pass in this, referencing the current object and ensuring it is an instanceof an allowed class. But any class could pass in an instance of an allowed class an so this seems to be an poor solution.
I also stumbled across Exception().getStackTrace()[1].getClassName(); however I am led to believe this is quite an expensive operation.
Is there a correct way to do this?
Use a marker interface (one that doesn't have any methods):
public interface Permissible {}
Then have the classes that are allowed to call your method implement it, then change the parameter type of your method to this interface:
public static void myMethodForObjectsThatHavePermission(Permissible obj) {
//
}
There's no way to enforce it that can't be worked around, but you could have most of your functionality on one class, setPermission() on a subclass, and make clients get an instance of your class via a factory method that is declared to return the parent class, but actually returns an instance of the subclass. That way, code that is supposed to call setPermission(), and knows about it, can do a downcast and call it, and all other users of the class won't even see it.
public class Service {
protected boolean permission = false;
protected Service() {
/* control creation */
}
public static Service getService() {
return new RealService();
}
public void doStuff() {
/* the public API side of the service */
}
}
public class RealService extends Service {
protected RealService() {
/* control creation */
}
public void setPermission(boolean permission) {
this.permission = permission;
}
}
A legitimate caller can do this:
public class Legitimate {
public void method() {
Service service = Service.getService();
RealService real = (RealService) service;
real.setPermission(true);
}
}
However, if all the legitimate callers can be put into the same package, and all the rest are outside the package, then package-private access (no access modifier) for setPermission() would be sufficient.
This doesn't prevent malicious callers from getting around the restriction, but it does avoid people calling setPermission without realizing they're not supposed to, because setPermission wouldn't show up in autocompletion (intellisense) in an IDE.
Sounds to me like you're looking for OSGi (en.wikipedia.org/wiki/OSGi). Third party developers should write bundles and with OSGi you can restrict capabilities of their bundles. Put your attention to: "Security The layer that handles the security aspects by limiting bundle functionality to pre-defined capabilities." Here is a thread discussing your case: Managing access to OSGI bundles
I have an abstract class that a child class extends. My abstract class has an #Activate method, so does the child class. When OSGi creates my service, it invokes the child class activate method but never the abstract class's activate. Is there any way to force the abstract class's activate to be called by OSGi rather than having the child class manually call the parent activate method?
Here is some code to help elaborate on what I am asking.
#Component(componentAbstract=true, inherit=true)
#Service(value=ISomeInterface)
public abstract class AbstractHello implements ISomeInterface{
#Activate
public void activate(){
System.out.print("Hello ");
}
}
#Component
#Service(Value=ISomeInterface)
public class World extends AbstractHello{
#Activate
public void activate(){
System.out.println("World!");
}
}
The result of the code above would be "World!", rather than "Hello World!".
Initially I thought maybe the child activate method name was clobbering the abstract activate method of the same name. The result is the same even if the abstract class's activate method is given a unique name. Is there any way to have OSGi call the abstract class's activate method for me?
The DS annotation processors only look at the concrete class decorated with #Component. Super classes are not examined. Since the annotation processing is done at build time, super types may come from imported packages which are not chosen until runtime.
Also, the annotation processor generates component description XML from the annotations. So there can only be one activate="methodName" attribute in the XML. If you need the superclass' method called, then you need to call it from the subclass' method.
This has nothing to do with Apache Felix and OSGi, this is caused by poor understanding of Class Inheritance and Method Overriding in Java.
Your World class extends AbstractHello class and overrides its activate() method. If you want the AbstractHello.activate() method to be called then you must call it in
// Annotations excluded for readability.
public class World extends AbstractHello {
public void activate() {
super.activate();
System.out.println("World!");
}
}
OSGi can't help here.
UPDATE
Since the base class is abstract, and you don't have an instance of it, you can't call its method. Neither can OSGi container.
I am creating a Java library, as a final product in intend to distribute this .jar to developers.
I am "translating" my library from Objective-C where I control which classes header files are available to the developer. In other words I am only exposing to the developer a few classes they can handle.
In my Java library I am using packages and my package has grown quite big. So I decided to separate into different packages my models and controllers. But now the models I wanted to keep private I need to mark as public in order to use from the main package.
My question is does this go against what I was doing in Objective-C ?
For example I have an Event class which is really only used internally and I don't want the user to know about it or think about it. I have another class TimedEvent, which the user can get an instance of an manage.
In my Objective-C, I simply excluded Event class from the library public scope, allowing TimedEvent.
If I am making things more tidy in my library then it seems packages aren't the way. Since now, my main controller is in the main package and all the models are in another package - forced to have a public scope.
Opinions ?
This is possible with Java but there are reasons why (almost) no one does it...
If you put the implementation and the interface into the same package, then you can omit all access modifiers (private, protected, public) from classes and methods to give them "default" or "package" visibility: Only classes in the same package are allowed to see/use them.
Drawback: You'll have to mix API and implementation.
The other approach is to move the implementation into a package *.private.*. No more mixing of API and implementation but malicious users can easily access the implementation - it's just a naming convention. Like a STOP sign: It means something ("be careful") but doesn't actually stop you.
Lastly, you can implement the interface inside of the interface. For example:
public interface IFoo {
String getName();
private static class Foo implements IFoo {
public String getName();
}
public static class FooFactory {
public static IFoo create() { return new Foo(); }
}
}
Ugly, ain't it?
The common approach to controlling exposure of your classes to the world is hiding implementations behind interfaces and factories.
Create an interface for your TimedEvent, and a class for creating instances of TimedEvent interface
Put the interface in the main package, and the factory in a sub-package
Give the factory public visibility
Implement the interface in the sub-package, giving it package visibility
Create an instance of the class implementing the TimedEvent interface in the factory
Here is an example of how you can do it:
package com.my.main;
public interface TimedEvent {
void fire();
}
package com.my.main.events;
import com.my.main;
public class EventFactory {
public TimedEvent makeTimedEvent() { return new TimedEvent (); }
}
// TimedEventImpl has package visibility - it is not public.
class TimedEventImpl implements TimedEvent {
public void fire() {
// Fire a timed event
}
}
The users would access TimedEvent like this:
com.my.main.events.EventFactory f = new com.my.main.events.EventFactory();
com.my.main.TimedEvent evt = f.makeTimedEvent();
evt.fire();
I have a class defined by an interface
public interface Test {
void testMethod();
}
Test test = new TestImpl();
public class TestImpl implements Test {
#Override
public void testMethod() {
//Nothing to do here
}
public void anotherMethod() {
//I am adding this method in the implementation only.
}
}
How can I call anotherMethod?
test.anotherMethod(); //Does not work.
I want to be able to define a few methods in the implementation only because in my production code, the Test interface covers a pretty broad spectrum of classes and is implemented by multiple classes. I use methods defined in the implementation to set dependencies that aren't covered by the DI framework in my unit testing so the methods change from implementation to implementation.
The problem is with the following line:
Test test = new TestImpl();
This tells the compiler to forget that the new object is a TestImpl and treat it as a plain old Test. As you know, Test does not have anotherMethod().
What you did is called "upcasting" (casting an object to a more general type). As another poster has said, you can fix your problem by not upcasting:
TestImpl test = new TestImpl();
If you're sure that a Test object is really a TestImpl, you can downcast it (tell the compiler it is a more specific type):
Test test = new TestImpl();
:
((TestImpl) test).anotherMethod();
This is generally a bad idea, however, since it can cause ClassCastException. Work with the compiler, not against it.
use
TestImpl test = new TestImpl();
then
test.anotherMethod();//It will work now
I think through your Interface reference it is impossible to call any method which is not defined in that interface.
If you want to avoid casting directly to your implementation class, I would create another interface:
public interface SpecificTest extends Test {
void anotherMethod();
}
And then have your TestImpl implement that interface (which means you can declare it as either Test or SpecificTest ):
SpecificTest test = new TestImpl();
test.anotherMethod();
Of course you can access your methods as was answered above, but you should adhere to best practices in programming. So you if you can't add required methods to Interface1 create Interface2 that extends Inteface1 and finally add your methods.
You can call it if you cast to the implementing class, the one that implements that method In short:
Test test = new TestImpl();
// ... and later / somewhere else
((TestImpl) test).anotherMethod();
If you do not want to type cast it to the concrete class then you could make anotherMethod() as private method and call it inside testMethod() based on some logic.
for eg.
testMethod()
{
if(foo)
{
anotherMethod();
}
}
This is a workaround that you can use if you do not want to create new methods in child class , since you cannot call them using a parent class/interface reference.