3

I am facing a problem with Spring RMI I want to use RMI to connect my three-tier system. I have DOA packages in the first tier, in the second tier there are services and controller for consuming a web service I want to connect the first tier with the second using RMI and I am facing problems with auto wiring the server to my RMI client.

@SpringBootApplication
@ComponentScan("sep.via.dk.sep3JPA")
public class Sep3JpaApplication {

    @Bean
    public  RemoteServer createBarServiceLink() {
          RmiProxyFactoryBean rmiProxyFactoryBean= new RmiProxyFactoryBean();
        rmiProxyFactoryBean.setServiceUrl("rmi://localhost:1099/helloworldrmi");
        rmiProxyFactoryBean.setServiceInterface(RemoteServer.class);
        rmiProxyFactoryBean.afterPropertiesSet();
        System.out.println("client is running");
        return (RemoteServer) rmiProxyFactoryBean.getObject();
    }
    public static void main(String[] args) throws AccessException, RemoteException, NotBoundException {
         RemoteServer helloWorldRMI= SpringApplication.run(Sep3JpaApplication.class, args).getBean(RemoteServer.class);
         RmiClient client = new RmiClient(helloWorldRMI);
         System.out.println("================Client Side ========================");
         System.out.println(helloWorldRMI.sayHelloRmi("FADI"));
    }

Configuration

@Configuration
public class Config {

    @Bean
    RemoteExporter registerRMIExporter() {

        RmiServiceExporter exporter = new RmiServiceExporter();
        exporter.setServiceName("helloworldrmi");
        exporter.setServiceInterface(RemoteServer.class);
        exporter.setService(new RmiServer());
        System.out.println("server is running");

        return exporter;   
    }

Client

public class RmiClient {

    private RemoteServer server;

    public RmiClient(RemoteServer server) throws AccessException, RemoteException, NotBoundException {
        this.server=server;
    }

    public void addCustomer(Customer customer) throws RemoteException {
        server.getCustomerDAO().addCustomer(customer);

    }

Service

@Service
public class CustomerServiceImplementation implements CustomerService {

    @Autowired
    public RmiClient rmiClient;

    @Autowired
    public MyPayment myPayment;

    @Override
    public boolean addCustomer(Customer customer) throws RemoteException {
        boolean checkPayment = checkPayment();
        if(checkPayment!=true) {
            return false;
        }

**************************
APPLICATION FAILED TO START
***************************

Description:

Field rmiClient in sep.via.dk.sep3JPA.service.customerService.CustomerServiceImplementation required a bean of type 'sep.via.dk.sep3JPA.rmiClient.RmiClient' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'sep.via.dk.sep3JPA.rmiClient.RmiClient' in your configuration.

please any help can be great

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
Fadi
  • 203
  • 4
  • 14
  • worth to mention that I have no xml configuration in this project. thanks in advance – Fadi Dec 16 '18 at 18:31
  • 1
    I tried aloso to Autowire the server in the client class, but it did not work either. it turnes out that the server instance was null all the time – Fadi Dec 16 '18 at 18:34
  • The error already tells you what you should do. Make your `RmiClient` a Spring managed bean. On the other hand why bother and just ditch this class as it doesn't add anything apart from leaking RMI details into your service which you are actually trying to prevent. Also why use RMI if they are part of the same application why add this complexity and overhead? – M. Deinum Dec 16 '18 at 18:42
  • thanks for the answer, but I am new to spring and I did not understand how make RMIClient a spring managed bean. I tried to add @component to it but it did not solve the problem. – Fadi Dec 16 '18 at 18:45
  • How would that be different compared to your `CustomerServiceImplementation`? It is exactly the same. – M. Deinum Dec 16 '18 at 18:45
  • I tried to annotate it as a Service but it still complaining and now the connection is refused java.net.ConnectException: Connection refused: connect – Fadi Dec 16 '18 at 18:49
  • Unsatisfied dependency expressed through field 'customerService' – Fadi Dec 16 '18 at 18:50
  • to answer you about the difference between service implementation and RmiClient class, I have a lot of service classes and I am delivering the methods from the server to the services through RmiClient class – Fadi Dec 16 '18 at 18:55
  • Don’t... Just inject the services you need don’t try to create one God RMI class. This also beats the purpose of using Spring Remoting which makes it agnostic of the underlying technologie, your RmiClient is in name and method signaturen a leaky abstraction in that regard. Next you are using the `RmiProxyFactoryBean` wrong. Don’t call `getObject` and `afterPropertiesSet` just return the factor. Spring will take care of the rest. Finally I still don’t understanding why you are using RMI to call objects in the same application. – M. Deinum Dec 16 '18 at 19:26
  • first I want to thank you, second, I tried to do what you told but now I got this error:org.springframework.remoting.rmi.RmiProxyFactoryBean cannot be cast to sep.via.dk.sep3JPA.rmi.RemoteServer – Fadi Dec 16 '18 at 20:43
  • @Bean public RemoteServer createBarServiceLink() { RmiProxyFactoryBean rmiProxyFactoryBean= new RmiProxyFactoryBean(); rmiProxyFactoryBean.setServiceUrl("rmi://localhost:1099/helloworldrmi"); rmiProxyFactoryBean.setServiceInterface(RemoteServer.class); return (RemoteServer) rmiProxyFactoryBean ; } – Fadi Dec 16 '18 at 20:44
  • I am using RMI just to fulfill the requierment for my semester project. I removed the RmiClient class since notified me to that it is a God RMI class, which you are totally right in this point, thanks for that – Fadi Dec 16 '18 at 20:46
  • Return the `RmiProxyFactoryBean` spring knows that and will do the rest. Again it doesn’t make any sense to use RMI to locale call another object. YOu need at least a client and a server, don’t try to do this in the same application. – M. Deinum Dec 16 '18 at 20:50
  • I did as you said and I am now more confused, I separated the project to two projects. the first project has the model, the dao and the RMIserver which will be exported to the client. But when I am implementing the same interface in the second project, which contains the services and the controller, I have to copy the model to the second project as well. do you have any suggestions regarding that. – Fadi Dec 16 '18 at 21:56
  • Everything that is used in the interface needs to be on either side of the connection. That is the drawback of using Java based couplings like this. – M. Deinum Dec 17 '18 at 07:20

0 Answers0