I want to add my class as an argument in the stateless, remote interface. For example:
In my remote interface I have this method
void connect(MyClass myClass);
But I didn't import MyClass (which is a Java Class library) in my interface, so I got an error. Is there any workaround?
In my SessionRemote class I imported MyClass library. Is there any chance to override that method in SessionRemote without importing MyClass in the interface?
#Override
public void connect(MyClass myClass){
myClass.foo();
}
I tried to add MyClass library to the interface, but I got lots of errors.
Related
I want to create a Java IPC server module (with Jigsaw) which has two packages:
com.example.ipc.backend
com.example.ipc.backend.api
in my module-info.java I have the following export:
module ipclib {
exports com.example.ipc.backend.api;
}
I can import this module in my JavaFX GUI module without problems, but I'm having a problem creating a class inside the api module.
I have one interface in this class which some class in the GUI module should implement to register itself for changes in the IPC module (e.g. when a client connects to the IPC server):
public interface IpcCallback {
void clientConnected(Client client);
}
The class which implements this interface should then receive a Client with the information about the connected client. This Client class also internally holds a reference to the thread which holds the socket to the client.
public class Client {
private IpcConnection connection; //IpcConnection is from com.example.ipc.backend
public Client(IpcConnection connection) {
this.connection = connection;
}
}
My problem is now that I want to create an instance of Client in the non-exported backend module, whenever a new connection is created. How can I make the constructor to be only accesible within the module, without making it public?
If I make the constructor public, IntelliJ offers to use the constructor to create a new Client object in the GUI module, but does not have access to the IpcConnection class. It offers a quick fix to export the backend module, but this is not what I want when exporting the api.
Therefore, I wonder if this is still “allowed”, because the Java compiler compiles this without any warnings and problems, and it is just a problem of IntelliJ. Or shouldn't this be done like this?
But if this is not the allowed way to do so, I wonder why the module system actually allows exporting only some packages, as there will always be a boundary between exported packages and not-exported packages (only except if the not-exported classes are called from within the exported class, but not the other way round).
Minimal project
Module 'backend'
// backend/src/main/java/module-info.java
module ipclib {
exports com.example.ipc.backend.api;
}
// backend/src/main/java/com/example/ipc/backend/IpcConnection.java
package com.example.ipc.backend;
public class IpcConnection {
}
// backend/src/main/java/com/example/ipc/backend/api/Client.java
package com.example.ipc.backend.api;
import com.example.ipc.backend.IpcConnection;
public class Client {
private IpcConnection connection;
public Client(IpcConnection connection) {
this.connection = connection;
}
public String hello() {
return "Hello";
}
}
// backend/src/main/java/com/example/ipc/backend/api/IpcCallback.java
package com.example.ipc.backend.api;
public interface IpcCallback {
void clientConnected(Client client);
}
Module 'gui'
// gui/src/main/java/module-info.java
module gui {
requires ipclib;
}
// gui/src/main/java/com/example/ipc/gui/App.java
package com.example.ipc.gui;
import com.example.ipc.backend.api.Client;
import com.example.ipc.backend.api.IpcCallback;
public class App implements IpcCallback {
public static void main(String[] args) {
}
#Override
public void clientConnected(Client client) {
System.out.println(client.hello());
}
}
I think, this is not possible in java. You can not declare an interface that is "visible in namespace A and all its sub-namespaces").
In contrast to .net, Java does not really know about the "internal" principle.
If you just omit the word public on an interface or class definition, this element is only visible inside it's current package.
But this is not recursive, as it is in .net (where you create an internal object which is visible only inside the current project, no matter which subfolder or namespace).
In Java, the object is only visible inside its current package (i.e. the very same namespace). Sub-namespaces are not included. Neither are parent namespaces.
If I understood correctly you have subpackages A and B, and only A is made public. A has a class C that has a constructor that should be called from B but not be made public.
I think your best option is to make class C (Client) implement and interface that is public. So the interface class can be in the public package and the actual implementation can be in the non-public package.
Given this code:
package my.pkg;
import com.google.common.util.concurrent.Service;
class Test implements Service {
public static void main(String... a) {
System.out.println(Listener.class);
}
// method implementations omitted for brevity
}
And given there's one Listener class in my.pkg, and one as an inner class in the Service class I'm importing.
I would expect the package local class to 'win' here, since I'm not referring to Service.Listener.class or explicitly importing the inner class. Apparently, IntelliJ expects the same thing, since if I explicitly add import my.pkg.Listener;, it is automatically removed as being redundant. However, when compiling and running this code (Gradle 2.14.1 and openjdk 1.8.0_91, if that matters), it's very clear the inner class is winning.
How do I get this code to use the class in my.pkg? Explicitly adding the import doesn't work, since my IDE removes it. I'd also prefer not to use full class names (my.pkg.Listener) everywhere in the class.
Salve...
some Problem for me in Java. I have generated an Interface and an Class implements this Interface. In the Interface i have declared one Method... and in the Class i will Override this. But not works! But don`t why....
See my example Interface:
public interface IMyClass extends IInterfaceA<IInterfaceB> {
public List<IInterfaceB> getMethod(Integer id);
}
See now my Class File:
public class MyClass implements IMyClass {
#Override
public List<IInterfaceB> getMethod(Integer id) {
return anything;
}
}
Problem is... i think i make no mistake. And next - i surprise that i have another Interfaces and Classes with the same Logic - and it will work and make no Problems!
In my another Interfaces & Classes i don`t need to make the Class with implements the Interface an Abstract Class.
When i make an build... Jenkins will surprise me with this Message:
[ERROR] COMPILATION ERROR :
error: MyClass is not abstract and does not override abstract method getMethode() in IMyClass [ERROR]
error: method does not override or implement a method from a supertype [INFO] 2 errors [INFO]
Solved . The " solution " - was a build problem . After tens of Maven Clean Installs and re- builds he has the connection interface and class savvy and it goes... oh men ;)
I'm studying for Java SE 7 certification exam and I'm doing some boring excercises about inheritance and access modifiers.
But now I'm getting an unexpected behavior applying inheritance. In my base package com.testpkg I have an abstract class:
package com.testpkg;
public abstract class Abstract {
public int test();
}
NOTE that I voluntarily omitted the abstract modifier for the test() method.
Then I have a concrete class extending Abstract in package com.testpkg.sub:
package com.testpkg.sub;
public class Concrete extends Abstract {
public int test() {
return 0;
}
}
I test this classes using:
package com.testpkg;
import com.testpkg.sub.Concrete;
public class TestMain {
public static void main(String[] args) {
Abstract c = new Concrete();
System.out.println(c.test());
}
}
If I try to compile this, I obviously get two errors:
The method test() requires a body instead of a semicolon
But if I run test class: 0 is printed on console!
This seems very strange to me. Can you explain why the code is working even test() is wrongly declared in Abstract class?
NOTE I'm using Eclipse IDE to compile/run my code.
You need an abstract qualifier on your test() method. You're likely running an old class file. If you change the value of your return statement to something besides 0, you will see that it isn't running this code.
Eclipse allows you to run "half baked" code. The reason why it runs fine here is because, at runtime, you never really depend on the specifics of the Abstract class so it doesn't really matter if you have this type of compile error in it.
Yours class Abstract has compilation errors, because non abstract method should be defined, so it should have a body. abstract qualifier is optional only in case of interfaces.
I have several classes which implement two interfaces. All of them implement the BaseInterface and some other interface which is specific to them.
I want to be able to use the loadClass method below to instantiate classes which are referred to in a .properties file and call the common method they all contain (because they implement BaseInterface).
public interface BaseInterface {
public void doBase();
}
public interface SpecificInterface extends BaseInterface {
public void doSpecific();
}
public class SpecificClass implements SpecificInterface {
public void doBase() { ... }
public void doSpecific() { ... }
}
public class LoadClass() {
private PropertiesLoader propertiesLoader = new PropertiesLoader();
public <C extends BaseInterface> C loadClass(String propertyName) {
Class<C> theClass;
// Load the class.
theClass = propertiesLoader.getPropertyAsClass(propertyName);
// Create an instance of the class.
C theInstance = theClass.newInstance();
// Call the common method.
theInstance.doBase();
return theInstance;
}
}
Unfortunately, when I run the code:
loadClassInstance.loadClass("SpecificClass");
I get the following exception:
Exception in thread "main" java.lang.ClassCastException:
SpecificClass cannot be cast to BaseInterface
at LoadClass.loadClass
Any ideas how I would solve this issue?
Many Thanks, Danny
Java's Service Provider Interface (SPI) libraries allow you to load classes with public parameterless constructors dynamically based on the interfaces they implement, and it's all done through the use of META-INF/services.
First, you'll need the interface:
package com.example;
public interface SomeService {
String getServiceId();
String getDisplayName();
}
Then when you need them, you can load them using Java's ServiceLoader class, which implements Iterable:
ServiceLoader<SomeService> loader = ServiceLoader.load(SomeService.class);
for (SomeService serv : loader) {
System.out.println(serv.getDisplayName());
}
Then when you have 1 or more implementing classes on your classpath, they register themselves in META-INF/services. So if you have the implementation:
package com.acme;
public class SomeImplementation implements SomeService {
// ...
public SomeImplementation() { ... }
// ...
}
Note that this class needs a default no-args constructor, this is not optional.
You register it with the class loader by creating a file in META-INF/services in your classpath (such as in the root of your jar) with the following properties:
The name of the file is the fully qualified class name of the interface, in this case, it's com.example.SomeService
The file contains a newline-separated list of implementations, so for the example implementation, it would contain one line: com.acme.SomeImplementation.
And there you go, that's it. How you build your project will determine where you put the META-INF/services stuff. Maven, Ant, etc. all have ways of handling this. I recommend asking another question about your specific build process if you have any trouble adding these files to your build.
If you replace your code with below it works. I doubt that PropertiesLoader is doing something that is not supposed to be done.
Class<?> theClass;
// Load the class.
theClass = Class.forName("SpecificClass");
// Create an instance of the class.
C theInstance = (C) theClass.newInstance();
BaseInterface base = loadClass();//There is no problem in casting
Java program normally is loaded by system classloader. The classes which are referred to in a .properties file are loaded by a user-defined classloader. Classes loaded by different classloaders are considered different even if have same name and are loaded from same classfile. In your case, the interface BaseInterface loaded by system classloader is different from the BaseInterface loaded by
PropertiesLoader.
To fix this, PropertiesLoader should delegate loading of BaseInterface to system classloader. Typical way to do so is to use system classloader as a parent classloader for PropertiesLoader.