Hi,
As Chetan mentioned JCR sessions are synchronous. However IIUC, you are
wrapping operations on sessions into futures in your code. So I would
guess you would have to use the future API to determine the state of the
wrapped operation (e.g. via a completion handler).
Michael
On 26.09.17 20:24, yogesh upadhyay wrote:
Hello,
We are working on a small CMS using Oak-Core (Version 1.6.0) with Play
framework and RDBMS as datastore.
"mysqlConnectorJava": "mysql:mysql-connector-java:5.1.38",
"oak-jcr": "org.apache.jackrabbit:oak-jcr:1.6.0",
We use the following code for session handle,
public <T> CompletableFuture<T> withSession(final FunctionWithCE<T> operation) {
final CompletableFuture<T> completableFuture = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
Session session = null;
try {
session = _repository.login(_credentials);
completableFuture.complete(operation.<T> apply(session));
} catch (Exception e) {
logger.error("Something went wrong while using session {}", e);
completableFuture.completeExceptionally(e);
} finally {
if (session != null) {
session.logout();
}
}
}, (Runnable command) -> {
ExecutionContexts.repositoryOperation().execute(command);
});
return completableFuture;
}
And this is how repository component is set up
@Inject
public RepositoryComponentImpl(final ApplicationLifecycle applicationLifecycle,
Database database,
Configuration configuration) {
final String jcrUsername = configuration.getString("jcrUsername");
final String jcrPassword = configuration.getString("jcrPassword");
if (jcrPassword != null || jcrUsername != null) {
_credentials = new SimpleCredentials(jcrUsername,
jcrPassword.toCharArray());
final DocumentMK.Builder documentMkBuilder = new DocumentMK.Builder();
documentMkBuilder.setAsyncDelay(3000);
documentMkBuilder.setPrefetchExternalChanges(true);
final DocumentNodeStore documentNodeStore =
documentMkBuilder.setRDBConnection(database.getDataSource()).getNodeStore();
_repository = new Jcr(new Oak(documentNodeStore)).createRepository();
final CompletableFuture<Void> setupCompletable = withSession((Session
session) -> setupRepository(session));
setupCompletable.exceptionally(e -> {
/*
* If there is an exception, log the message and rethrow, otherwise it
would be
* lost in the other thread and not surfaced
*/
logger.error(e.getMessage(), e);
throw new CompletionException(e);
});
applicationLifecycle.addStopHook(() -> {
documentNodeStore.dispose();
return F.Promise.pure(null);
});
} else {
throw new IllegalStateException("Unable to get repository credentials.");
}
}
And this is how session is being used in save operation,
public CompletableFuture<Void> deleteBlob(String blobId) {
return _repositoryComponent.withSession((Session session) -> {
session.getNode("/asset/").getNode(blobId).remove();
session.save();
return (null);
});
}
For read operations, we use new session again.
Now the problem we are running into is, after save operation is performed,
there is no good way for us to know if save was done (Since save in oak is
async). So after save we refresh the page, the user sees old content.
We can provide some kind of delay on redirect to remedy this issue but it
won't be good user experience.
We are wondering, if there Is any good way to find if after
"session.save()" is called, data is saved in RDBMS and now all new session
will get updated data? Or we are doing anything wrong here.
Yogesh