Home » Modeling » EMF » [CDO] Queries related to Standalone Client - Reg.(This question is related to the implementation of a Standalone Java Client (outside the Eclipse IDE) which makes use of CDO to store the models and retrieve it.)
[CDO] Queries related to Standalone Client - Reg. [message #1785992] |
Mon, 23 April 2018 22:51 |
Nirmal Kanagasabai Messages: 8 Registered: January 2018 |
Junior Member |
|
|
Hello Team,
We have built a stand-alone modelling application which is built on top of EMF. As the application doesn't run in Eclipse IDE, I, unfortunately, cannot take advantage of the amazing 'CDO Explorer' Perspective. I might have to implement them to suit our application.
I made use of the Standalone Java Client that you provided and understood the working methodology. I thought I just had to get the resource from the repository and load it into my application.
When you said, 'the changes are automatically reflected in all the clients', I was able to visualize them in CDO Explorer. But, the question is, how does this happen when we are having a stand-alone application?
I also came across this interesting resource while reading about it:
As it was quoted by you in this video @ 21:15,
Instead of opening a new CDO Session, you ask us to do the following:
1) From the View of an input object, we have to retrieve the underlying session.
2) From there, we need to open a new transaction.
3) Using the transaction, we have to get a transactional version of the object.
I am extremely sorry if the question sounds silly. Being a newbie, I am lost mid-way reading about this and I am unable to go ahead.
Does this mean, I have to load the model differently from the database instead of transaction.getResource(path/to/the/resource)?
I will be extremely glad if you can help me out on this regard.
|
|
|
Re: [CDO] Queries related to Standalone Client - Reg. [message #1786000 is a reply to message #1785992] |
Tue, 24 April 2018 03:56 |
|
Hi Nirmal,
The CDO core is indeed mostly independent of the OSGi and Eclipse cores. The main difference of a stand-alone application is that you're required to prepare CDO's IManagedContainer manually, while in Eclipse that's done through the extension registry. Here's a small example:
public class StandaloneContainerExample
{
public static void main(String[] args) throws CommitException
{
// Enable logging and tracing
OMPlatform.INSTANCE.setDebugging(true);
OMPlatform.INSTANCE.addLogHandler(PrintLogHandler.CONSOLE);
OMPlatform.INSTANCE.addTraceHandler(PrintTraceHandler.CONSOLE);
// Prepare container
IManagedContainer container = ContainerUtil.createContainer();
Net4jUtil.prepareContainer(container); // Register Net4j factories
TCPUtil.prepareContainer(container); // Register TCP factories
CDONet4jUtil.prepareContainer(container); // Register CDO factories
container.activate();
// Create connector
IConnector connector = TCPUtil.getConnector(container, "localhost:2036"); //$NON-NLS-1$
// Create configuration
CDONet4jSessionConfiguration configuration = CDONet4jUtil.createNet4jSessionConfiguration();
configuration.setConnector(connector);
configuration.setRepositoryName("repo1"); //$NON-NLS-1$
// Open session
CDOSession session = configuration.openNet4jSession();
session.getPackageRegistry().putEPackage(CompanyPackage.eINSTANCE);
// Open transaction
CDOTransaction transaction = session.openTransaction();
// Get or create resource
CDOResource resource = transaction.getOrCreateResource("/path/to/my/resource"); //$NON-NLS-1$
// Work with the resource and commit the transaction
EObject object = CompanyFactory.eINSTANCE.createCompany();
resource.getContents().add(object);
transaction.commit();
// Cleanup
session.close();
connector.close();
container.deactivate();
}
}
Instead of creating your own container I recommend to use IPluginContainer.INSTANCE.
The model objects that are loaded through a CDO view or transaction will always be automatically updated to reflect the current remote version. A user interface, no matter what UI technology is used, is notified about these updates through a number of mechanisms:
- EMF Notifications that are delivered to the Adapters that you attached to your model objects. This is the standard mechanism, which also works well with your generated item providers, which you can use independent of a specific UI technology.
- CDOSessionInvalidationEvents that are sent to the IListeners that you added to your CDOSession.
- CDOViewInvalidationEvents that are sent to the IListeners that you added to your CDOView or CDOTransaction.
Regarding the "global read-only view and multiple transactional background actions" pattern that I mentioned in the video, there's a class in CDO that nicely demonstrates what it means:
public abstract class TransactionalBackgroundAction extends LongRunningAction
{
private final CDOObject object;
public TransactionalBackgroundAction(IWorkbenchPage page, String text, String toolTipText, ImageDescriptor image, CDOObject object)
{
super(page, text, toolTipText, image);
this.object = object;
}
public final CDOObject getObject()
{
return object;
}
protected CDOTransaction openTransaction(CDOObject object)
{
CDOView view = object.cdoView();
CDOTransaction transaction = view.getSession().openTransaction(view.getBranch());
CDOUtil.configureView(transaction);
return transaction;
}
@Override
protected final void doRun(IProgressMonitor progressMonitor) throws Exception
{
progressMonitor.beginTask(Messages.getString("TransactionalBackgroundAction_1"), 100); //$NON-NLS-1$
CDOTransaction transaction = openTransaction(object);
CDOObject transactionalObject = null;
CDOCommitInfo commitInfo = null;
try
{
transactionalObject = transaction.getObject(object);
progressMonitor.worked(5);
doRun(transaction, transactionalObject, new SubProgressMonitor(progressMonitor, 5));
commitInfo = transaction.commit(new SubProgressMonitor(progressMonitor, 90));
}
finally
{
progressMonitor.done();
transaction.close();
transactionalObject = null;
}
if (commitInfo != null)
{
CDOView view = object.cdoView();
view.waitForUpdate(commitInfo.getTimeStamp(), 5000);
postRun(view, object);
}
}
protected abstract void doRun(CDOTransaction transaction, CDOObject object, IProgressMonitor progressMonitor) throws Exception;
protected void postRun(CDOView view, CDOObject object)
{
}
}
I think it's self-explanatory. If not, don't hesitate to ask ;-)
Cheers
/Eike
Cheers
/Eike
----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper
|
|
| |
Re: [CDO] Queries related to Standalone Client - Reg. [message #1792234 is a reply to message #1786052] |
Fri, 13 July 2018 05:51 |
Nirmal Kanagasabai Messages: 8 Registered: January 2018 |
Junior Member |
|
|
Hello Eike,
I am back with some more questions on the notification of remote changes. From all the posts I came across in the forum and your response to my previous query, I realize that the 3 ways to go about are CDOSessionInvalidationEvent, CDOViewInvalidationEvent, and EMFNotification.
However, I am totally confused as to how I implement it in my application. Can you please offer sample snippets where a CDOSessionInvalidationEvent / CDOViewInvalidationEvent is dealt with like the way you did for Stand-alone client? That would help a newbie like me big time.
Also, the application that we currently have makes use of the standard EMF notifications. There are adapters that are attached to the model objects. Right now, I am able to persist and load model objects onto my standalone Java application (client). When two instances (of our application) are running and say, I add a class in one of the instances, I do not see any change happening in the other client. When I re-load the model, I find the changes in there. I understand that I am missing something but I ain't sure of what it is. Changes happening locally in the client works without any hassle.
I humbly request you to help me out on this regard.
|
|
|
Re: [CDO] Queries related to Standalone Client - Reg. [message #1792254 is a reply to message #1792234] |
Fri, 13 July 2018 09:45 |
|
IMO there are only rare occasions where a CDOSessionInvalidationEvent listener would make sense. An example of a CDOViewInvalidationEvent listener can be found in org.eclipse.emf.cdo.ui.CDOEventHandler.viewListener.
To check whether and what events occur in your second client you can temporarily add this code:
transaction.getSession().addListener(new org.eclipse.net4j.util.event.EventPrinter());
transaction.addListener(new org.eclipse.net4j.util.event.EventPrinter());
Can you see invalidation events in the console now? If you see the events occuring, but your EMF adapters aren't notified, you can try one of the following:
1. session.options().setPassiveUpdateMode(PassiveUpdateMode.CHANGES);
2. transaction.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);
Does that make any difference?
Cheers
/Eike
----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper
|
|
|
Re: [CDO] Queries related to Standalone Client - Reg. [message #1792278 is a reply to message #1792254] |
Fri, 13 July 2018 19:38 |
Nirmal Kanagasabai Messages: 8 Registered: January 2018 |
Junior Member |
|
|
Hello Eike,
Thank you very much for your quick reply. I included the code snippet that you have mentioned above. Here's what I receive in my console:
P.S.: There were several ContainerEvents, CDOSessionInvalidationEvents, CDOSessionLocksChangedEvent and CDOViewAdaptersNotifiedEvents. I removed them for the sake of clarity.
ContainerEvent[source=Session36 [repo1], ADDED=Transaction 35 [MAIN]]
CDOTransactionStartedEvent[source=Transaction 35 [MAIN]]
CDOTransactionFinishedEvent[source=Transaction 35 [MAIN], cause=COMMITTED, idMappings=0]
CDOSessionInvalidationEvent[CommitInfo[2018-07-13 15:23:20.287 (1531509800287), Branch[id=0, name=MAIN], null, null, null, CommitData[newPackageUnits=0, newObjects=14, changedObjects=1, detachedObjects=0]]]
CDOSessionLocksChangedEvent[source=Session36 [TouchCORE_Repo], sender=Transaction 35 [MAIN], null]
CDOViewAdaptersNotifiedEvent[source=Transaction 6 [MAIN], timeStamp=1531509800287]
CDOViewAdaptersNotifiedEvent[source=Transaction 7 [MAIN], timeStamp=1531509800287]
CDOViewAdaptersNotifiedEvent[source=Transaction 18 [MAIN], timeStamp=1531509800287]
CDOViewAdaptersNotifiedEvent[source=Transaction 31 [MAIN], timeStamp=1531509800287]
CDOViewAdaptersNotifiedEvent[source=Transaction 14 [MAIN], timeStamp=1531509800287]
CDOTransactionFinishedEvent[source=Transaction 35 [MAIN], cause=COMMITTED, idMappings=0]
It says that the CDOViewAdapters have been notified. Does this mean that I have missed something in my client implementation that, even after receiving the notifications, the changes aren't reflected?
Here's a small snippet from my application where one of the handlers that are responsible for creating a new class is handling the EMF notification.
aspect.eAdapters().add(new EContentAdapter() {
private Class clazz;
@Override
public void notifyChanged(Notification notification) {
if (notification.getFeature() == eINSTANCE.getStructuralView_Classes()) {
if (notification.getEventType() == Notification.ADD) {
clazz = (Class) notification.getNewValue();
}
} else if (notification.getFeature() == eINSTANCE.getContainerMap_Value()) {
if (notification.getEventType() == Notification.ADD) {
((ClassView) view.getClassViewOf(clazz)).showKeyboard();
((ClassView) view.getClassViewOf(clazz)).clearNameField();
aspect.eAdapters().remove(this);
}
}
}
});
I would be extremely glad if you can explain what is expected from a client implementation's perspective? I am extremely sorry if this question sounds very silly.
[Updated on: Sat, 14 July 2018 03:32] Report message to a moderator
|
|
| | |
Goto Forum:
Current Time: Thu Sep 19 23:59:22 GMT 2024
Powered by FUDForum. Page generated in 0.03278 seconds
|