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 ICredentialVerifier
interface. 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?
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 IMySqlAuthService
with @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