javaeclipse-scout

Eclipse Scout - Clean Database authentication


I'm trying to implement a database authentication with Eclipse Scout.

For that I created a class DataSourceCredentialVerifier in the client module, which implements the ICredentialVerifierinterface. Then I adapted the init method of the UiServletFilter class to use my verifier.

public class DataSourceCredentialVerifier implements ICredentialVerifier {

private static final Logger LOG = LoggerFactory.getLogger(DataSourceCredentialVerifier.class);

@Override
public int verify(String username, char[] password) throws IOException {
    Object queryResult[][] = BEANS.get(IMySqlAuthService.class).load();


    return AUTH_OK;
}

I haven't implemented any authentication logic yet. My task now is to establish a clean database connection.

For that I created the following interface in the shared module:

public interface IMySqlAuthService extends IService {

    Object[][] load();
}

The implementation is in the server module:

   public class MySqlAuthService implements IMySqlAuthService {

        @Override
        public Object[][] load() {
            String sql = "select username, password from users ";
            Object[][] queryResult = SQL.select(sql, null, null);       
            return queryResult;
        }
   }

First I want to see, if there is at least something in the query, but I get an AssertionException here:

 Object queryResult[][] = BEANS.get(IMySqlAuthService.class).load();

org.eclipse.scout.rt.platform.util.Assertions$AssertionException: Assertion error: no instance found for query: interface org.eclipse.scout.app.shared.services.IMySqlAuthService
at org.eclipse.scout.rt.platform.util.Assertions.fail(Assertions.java:580)
at org.eclipse.scout.rt.platform.util.Assertions.assertNotNull(Assertions.java:87)
at org.eclipse.scout.rt.platform.BEANS.get(BEANS.java:41)

I don't get an instance of my MySqlAuthService implementation. I assume that the BeanManager should have created an instance for me. MySqlAuthService should be registered as a Bean, since my IMySqlAuthService interface extends from IService which has the @ApplicationScoped annotation.

Adding the @Bean annotation to MySqlAuthService results in the same exception.

Here some information about the BeanManager and annotations: https://eclipsescout.github.io/6.0/technical-guide.html#sec-bean.manager

Here is another different approach s.o. tried, but it doesn't feel correct: https://www.eclipse.org/forums/index.php/t/1079741/

How can I get my example to work with my service?


Solution

  • Here is the working solution with important explanations of Eclipse Scout principles.

    The source is summarized information of the Eclipse-Scout-Technical-Guide.

    In Scout there is a built in annotation: @TunnelToServer. Interfaces marked with this annotation are called on the server. The server itself ignores this annotation. To achieve that a bean is registered on client side, this annotation is required. The platform cannot (!) directly create an instance for these beans, a specific producer is registered which creates a proxy that delegates the call to the server.

    My first clear mistake was that I hadn't annotated the IMySqlAuthServicewith @TunnelToServer.

    After this addition I got rid of the no instance AssertionError.

    After that my code ran into the HTTP status-code: 403 access forbidden.

    This occured because my code didn't run in the correct Thread. That is the current RunContext. I had to use this lines of code in my verify method of the DataSourceCredentialVerifier:

         Subject subject = new Subject();
         subject.getPrincipals().add(new SimplePrincipal("system"));
         subject.setReadOnly();
         RunContext runContext = RunContexts.copyCurrent().withSubject(subject);
    

    Now one can use the runContext's call() or run() method, depending whether the code returns a result. The action is run in the current thread, meaning that the caller is blocked until completion.

    Concrete example solution:

    Object[][] result = runContext.call(new Callable<Object[][]>() {
    
       @Override
       public Object[][] call() throws Exception {
          return BEANS.get(IMySqlAuthService.class).load();
       }
    
    });
    
    //TODO implement authentication logic.
    

    For more information about the RunContext see here: https://eclipsescout.github.io/6.0/technical-guide.html#runcontext