Tuesday, November 24, 2015

OrientDB - Using plocal Embedded Storage from Two Processes

OrientDB has this nice feature of creating and using database in embedded mode. We can programatically create and accesses OrientDB database for CRUD operations without the server. We can create a plocal storage (Paginated Local Storage) with this. plocal is a disk based storage which works with data using page model. This storage is very fast because of we can assess the database directly with local mode.

But, plocal storage has a limitation; it can only be accessed by one process at a time. When a process accesses the database, it locks the database so that no other program or process can access that. This lock will not be released until the program terminates. It avoids updating the database from several processes.
If you are going to accesses the plocal db while another process has acquired the lock, you will have the following error message.

com.orientechnologies.orient.core.exception.OStorageException: Cannot open local storage 'C:/MyOrientDb/dbs/myPlocal' with mode=rw
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.open(OAbstractPaginatedStorage.java:217)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.open(ODatabaseDocumentTx.java:243)
at com.lakj.comspace.orientdb.PlocalTest.readDb(PlocalTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)...
Caused by: com.orientechnologies.orient.core.exception.OSerializationException: Cannot load database's configuration. The database seems to be corrupted.
at com.orientechnologies.orient.core.storage.impl.local.OStorageConfigurationSegment.load(OStorageConfigurationSegment.java:86)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.open(OAbstractPaginatedStorage.java:164)
... 28 more
Caused by: java.io.IOException: The process cannot access the file because another process has locked a portion of the file
at java.io.RandomAccessFile.read0(Native Method)
at java.io.RandomAccessFile.read(Unknown Source)
at com.orientechnologies.orient.core.storage.fs.OAbstractFile.openChannel(OAbstractFile.java:641)
at com.orientechnologies.orient.core.storage.fs.OAbstractFile.open(OAbstractFile.java:144)
at com.orientechnologies.orient.core.storage.impl.local.OSingleFileSegment.open(OSingleFileSegment.java:57)
at com.orientechnologies.orient.core.storage.impl.local.OStorageConfigurationSegment.load(OStorageConfigurationSegment.java:65)
... 29 more

 I found a solution to this problem!

When you want to share a plocal database among two (or more) processes, you can follow the following procedure.

Let's take a sample scenario. Two processes called Process-A and Process-B are going to access the same plocal storage named 'myPlocal'. Process-A reads the database. Then Process-B update the database and terminates. Then again Process-A reads the database.

Step 1:
Create the db connection from Process-A read the relevant data.
When the Process-A creates the db connection, it locks the db so that any other process cannot read or update the db.
ODatabaseDocumentTx dbProsA = new ODatabaseDocumentTx("plocal:/db/myPlocal");
dbProsA .open("admin", "admin");
Step 2:
Freeze the db from the Process-A.

Freeze method is used to create 'live' database backups. It flushes all cached content to the disk storage and allows to perform only read commands for current process. Here when the Process-A calls freeze method, no any thread from Process-A can write on db. But any thread from Process-A can read from db. More importantly, another process can acquire the db lock and update it. Here the Process-B will do it.
dbProsA .freeze();
Step 3:
Create the db connection from Process-B and read or update data. Then the Process-B terminates.
Because of Process-A has freezed it's connection Process-B can create a new connection and update the db. Here the Process-B should terminate and release the db so that the Process-A can get it back.
ODatabaseDocumentTx dbProsB = new ODatabaseDocumentTx("plocal:/db/myPlocal");
dbProsB.open("admin", "admin");
// Do whatever you want here 
dbProsB.close();
Step 4:
Process-A release the db.
If you freeze the db connection, you should call release method to enable it for write operations.
dbProsA .release();
Step 5:
Process-A restarts the db engine.

This is the most important step. Though you have release the db connection from Process-A, it won't be able to read the updates which has been done by Process-B. You may still read the data which you had at the point you freeze it.
To read the updated values from the Process-B you should re-start the db engine from Process-A. It's just two method calls; shutdown() and start().
OOrient instance = Orient.instance();
instance.shutdown();
instance.startup();
You are done..!
Now you have shared your plocal db between Process-A and Process-B.

Sunday, June 28, 2015

Why Circular Dependencies Between Java Packages are Bad?

No doubt, Circular dependencies between "Modules" (projects, jars, etc..) is BAD.
It has all the consequences which lead to problem in the areas like,

  • Maintainability
  • Re-usability
  • Testability
  • Compilation problems
  • Release and build problems
  • Domino defect
  • Memory leaks

But does it really matter when there are a circular dependencies between packages?


I was searching and reading about this, but i could not find an exact reasonable answer.
So the my opinion is, it's a design concern.

In the OO design principles (SOLID[1] principle) dependency is a major concern[2]. So when we design according to the OO model we should avoid circular dependencies.

Just imagine we are going to apart some packages form the program and maintain the program as a two different modules. Then the circular dependencies would make all the problem i mentioned for module dependencies. Therefore we can say circular dependencies reduces the extensibility of the program.

Packages are used to organize classes belonging to the same category or providing similar functionality[3]. When there is a circular dependency, according to my experience what i can say is, there should be components which represent a certain functionality or a category which can be re-organized to single package. Therefore if we are really following Java OO design guidelines, the circular dependencies should not be present.

Some programming languages (Eg: Go) don't allow circular dependencies (circular imports). But Java allows it. But we should pay the attention on proper OO design and avoid circles.


References:
[1] https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
[2] https://en.wikipedia.org/wiki/Dependency_inversion_principle
[3] https://en.wikipedia.org/wiki/Java_package

Monday, June 8, 2015

OrientDB - com.orientechnologies.common.exception.OException: Error on creation of shared resource

You got the following error...???
I got this error when i tried to connect a local (plocal / embedded) document OrientDB.

Solution: I had added both orientdb-core-*.jar and orientdb-client-*.jar libraries to the class path. I just removed  orientdb-client-*.jar. Then the error solved.

I don't know the exact reason for this problem. But in the OrientDB Document API document, it has been mentioned that  orientdb-client-*.jar is for connecting to a remote server. Therefore, orientdb-client-*.jar is not required to creating connections to plocal DB instances.


com.orientechnologies.common.exception.OException: Error on creation of shared resource
at com.orientechnologies.common.concur.resource.OSharedContainerImpl.getResource(OSharedContainerImpl.java:55)
at com.orientechnologies.orient.core.metadata.OMetadataDefault.init(OMetadataDefault.java:175)
at com.orientechnologies.orient.core.metadata.OMetadataDefault.load(OMetadataDefault.java:77)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.initAtFirstOpen(ODatabaseDocumentTx.java:2633)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.open(ODatabaseDocumentTx.java:254)
at com.lakj.comspace.orient.db.data.DBHandler.getData(DBHandler.java:51)
at com.lakj.comspace.orient.db.data.DBHandlerTest.testDBHandler(DBHandlerTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.orientechnologies.orient.core.exception.ORecordNotFoundException: The record with id '#0:1' not found
at com.orientechnologies.orient.core.record.ORecordAbstract.reload(ORecordAbstract.java:266)
at com.orientechnologies.orient.core.record.impl.ODocument.reload(ODocument.java:665)
at com.orientechnologies.orient.core.type.ODocumentWrapper.reload(ODocumentWrapper.java:91)
at com.orientechnologies.orient.core.type.ODocumentWrapperNoClass.reload(ODocumentWrapperNoClass.java:73)
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.load(OSchemaShared.java:786)
at com.orientechnologies.orient.core.metadata.OMetadataDefault$1.call(OMetadataDefault.java:180)
at com.orientechnologies.orient.core.metadata.OMetadataDefault$1.call(OMetadataDefault.java:175)
at com.orientechnologies.common.concur.resource.OSharedContainerImpl.getResource(OSharedContainerImpl.java:53)
... 30 more
Caused by: com.orientechnologies.orient.core.exception.ODatabaseException: Error on retrieving record #0:1 (cluster: internal)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.executeReadRecord(ODatabaseDocumentTx.java:1605)
at com.orientechnologies.orient.core.tx.OTransactionNoTx.loadRecord(OTransactionNoTx.java:80)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.reload(ODatabaseDocumentTx.java:1453)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.reload(ODatabaseDocumentTx.java:117)
at com.orientechnologies.orient.core.record.ORecordAbstract.reload(ORecordAbstract.java:260)
... 37 more
Caused by: java.lang.NoSuchMethodError: com.orientechnologies.common.concur.lock.ONewLockManager.tryAcquireSharedLock(Ljava/lang/Object;J)Z
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.acquireReadLock(OAbstractPaginatedStorage.java:1301)
at com.orientechnologies.orient.core.tx.OTransactionAbstract.lockRecord(OTransactionAbstract.java:120)
at com.orientechnologies.orient.core.id.ORecordId.lock(ORecordId.java:282)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.lockRecord(OAbstractPaginatedStorage.java:1779)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.readRecord(OAbstractPaginatedStorage.java:1425)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.readRecord(OAbstractPaginatedStorage.java:697)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.executeReadRecord(ODatabaseDocumentTx.java:1572)
... 41 more

Thursday, March 5, 2015

IntelliJ Plugin Development Tutorial - Get All Packages of a Module

This tutorial shows you how to get all the packages of a selected module in the IntelliJ IDE. When you run this plugin you will have an action button in project viewer. When you right click on a module and click the  "Lak J Show All Packages Action", a message window will show the all package names.

Following are the two files you want work with to create this plugin.

Following are the GitHub URL's for complete plugin project. You can clone the project or downolad the project as a zip file. To run the project open IntelliJ IDEA and import the project.

GitHub repository URL - https://github.com/lakjcomspace/IntelliJGetModulePackages
GitHub HTTPS clone URL - https://github.com/lakjcomspace/IntelliJGetModulePackages.git
Download Project as a Zip - https://github.com/lakjcomspace/IntelliJGetModulePackages/archive/master.zip


Sunday, January 25, 2015

IntelliJ Plugin Development Tutorial - Project View Popup Menu Action Item

This simple tutorial shows you how to create an Action Item in the Project View Popup Menu.
When  you right click on the project view you will have this action item in the popup menu. You can extend or use this to execute any action.

 Following are the two files you should work with.

Following are the GitHub URL's for complete plugin project. You can clone the project or downolad the project as a zip file. To run the project open IntelliJ IDEA and import the project.

GitHub repository URL - https://github.com/lakjcomspace/IntelliJProjectViewMenuAction
GitHub HTTPS clone URL - https://github.com/lakjcomspace/IntelliJProjectViewMenuAction.git
Download Project as a Zip - https://github.com/lakjcomspace/IntelliJProjectViewMenuAction/archive/master.zip



Wednesday, January 7, 2015

Android Client-Server Chat Application

This is a simple Android chat application which communicate with a Java server program. This tutorial will help you to understand socket programming in Android which sends information both ways.
To run this application, first execute the server program. You can run this application in your PC.

Then execute the client program. You can use your Android emulator or your Android device. If you are using Android emulator you can use IP address 10.0.2.2 to connect your sever which is running in the same computer. But if you are using an Android device you may have to change the IP address in the client app code according to your network configuration.
Once you execute the client app, the chat window will be opened in the server program. Type the message on the chat box and press "Send" button. The message will be appeared in the other end.

      
Android Chat App
 
Server Program





                                                         









                                                                                   
Following are the source codes of the main components of both programs.

Android Chat Application


Server Program


Following are the both Android client and Java server complete projects. You can clone or download them as zips from Git-Hub.

Git-Hub HTTPS clone URL: https://github.com/lakjcomspace/AndroidChatClientServer.git
Git-Hub Repository URL: https://github.com/lakjcomspace/AndroidChatClientServer
Download as a Zip: https://github.com/lakjcomspace/AndroidChatClientServer/archive/master.zip

You can run the projects by importing them to the IDE. Or just create you own project and copy and paste above source files.