Jackrabbit update or merge node - java

I have already send the same message to jackrabbit user list, but nobody reply me.
I would like to update a node and his childs with Jackrabbit 2.4.3 throw jackrabbit-jcr2dav. ( like a merge : updating, creating or removing nodes ).
But when I update a property already existing in the repository I have an ERROR in the log, and nothing is saved. It's not an exception, only an error.
[ERROR] org.apache.jackrabbit.jcr2spi.hierarchy.ChildNodeEntriesImpl:176 - ChildInfo iterator contains multiple entries with the same name|index or uniqueID -> ignore ChildNodeInfo.
my code :
Repository repository = JcrUtils.getRepository(jcrUrl);
Session session = repository.login( new SimpleCredentials("admin", "admin".toCharArray()));
try {
String user = session.getUserID();
String repositoryname = repository.getDescriptor(Repository.REP_NAME_DESC);
LOGGER.debug( "Logged in as " + user + " to a " + repositoryname + " repository.");
// Retrieve content
StringBuilder expression = new StringBuilder();
expression.append("SELECT * FROM [nt:unstructured] AS mynode ");
expression.append("WHERE id = "+ mynode.getId() +" " );
QueryManager queryMgr = session.getWorkspace().getQueryManager();
Query query = queryMgr.createQuery(expression.toString(),Query.JCR_SQL2);
QueryResult result = query.execute();
RowIterator rowIterator = result.getRows();
if (rowIterator.hasNext() ) {
Node node = rowIterator.nextRow().getNode();
// Store metadata content
node.setProperty("description", mynode.getDescription());
node.setProperty("keywords", mynode.getKeywords());
node.setProperty("title", mynode.getTitle()); // ERROR IN THE LOG AT THIS LINE because description and keywords doesn't exist, but title already exist.
node.setProperty("resume", mynode.getResume());
[... updating childs node here ]
session.save();
}
} catch ( RepositoryException e) {
LOGGER.error("Error getting data", e);
throw e;
} finally {
session.logout();
}
return book;
}
Is someone already try to update a node property ?
Thanks

Finally, I have confirmation that two nodes under the same parent should note have the same name. That's why I have this error.
Without having the same name, my code is working.

Related

getting first level of categorisation from Notes view

I have a categorized Notes view, let say the first categorized column is TypeOfVehicle the second categorized column is Model and the third categorized column is Manufacturer.
I would like to collect only the values for the first category and return it as json object:
I am facing two problems:
- I can not read the value for the category, the column values are emptry and when I try to access the underlying document it is null
the script won't hop over to the category/sibling on the same level.
can someone explain me what am I doing wrong here?
private Object getFirstCategory() {
JsonJavaObject json = new JsonJavaObject();
try{
String server = null;
String filepath = null;
server = props.getProperty("server");
filepath = props.getProperty("filename");
Database db;
db = utils.getSession().getDatabase(server, filepath);
if (db.isOpen()) {
View vw = db.getView("transport");
if (null != vw) {
vw.setAutoUpdate(false);
ViewNavigator nav;
nav = vw.createViewNav();
JsonJavaArray arr = new JsonJavaArray();
Integer count = 0;
ViewEntry tmpentry;
ViewEntry entry = nav.getFirst();
while (null != entry) {
Vector<?> columnValues = entry.getColumnValues();
if(entry.isCategory()){
System.out.println("entry notesid = " + entry.getNoteID());
Document doc = entry.getDocument();
if(null != doc){
if (doc.hasItem("TypeOfVehicle ")){
System.out.println("category has not " + "TypeOfVehicle ");
}
else{
System.out.println("category IS " + doc.getItemValueString("TypeOfVehicle "));
}
} else{
System.out.println("doc is null");
}
JsonJavaObject row = new JsonJavaObject();
JsonJavaObject jo = new JsonJavaObject();
String TypeOfVehicle = String.valueOf(columnValues.get(0));
if (null != TypeOfVehicle ) {
if (!TypeOfVehicle .equals("")){
jo.put("TypeOfVehicle ", TypeOfVehicle );
} else{
jo.put("TypeOfVehicle ", "Not categorized");
}
} else {
jo.put("TypeOfVehicle ", "Not categorized");
}
row.put("request", jo);
arr.put(count, row);
count++;
tmpentry = nav.getNextSibling(entry);
entry.recycle();
entry = tmpentry;
} else{
//tmpentry = nav.getNextCategory();
//entry.recycle();
//entry = tmpentry;
}
}
json.put("data", arr);
vw.setAutoUpdate(true);
vw.recycle();
}
}
} catch (Exception e) {
OpenLogUtil.logErrorEx(e, JSFUtil.getXSPContext().getUrl().toString(), Level.SEVERE, null);
}
return json;
}
What you're doing wrong is trying to treat any single view entry as both a category and a document. A single view entry can only be one of a category, a document, or a total.
If you have an entry for which isCategory() returns true, then for the same entry:
isDocument() will return false.
getDocument() will return null.
getNoteID() will return an empty string.
If the only thing you need is top-level categories, then get the first entry from the navigator and iterate over entries using nav.getNextSibling(entry) as you're already doing, but:
Don't try to get documents, note ids, or fields.
Use entry.getColumnValues().get(0) to get the value of the first column for each category.
If the view contains any uncategorised documents, it's possible that entry.getColumnValues().get(0) might throw an exception, so you should also check that entry.getColumnValues().size() is at least 1 before trying to get a value.
If you need any extra data beyond just top-level categories, then note that subcategories and documents are children of their parent categories.
If an entry has a subcategory, nav.getChild(entry) will get the first subcategory of that entry.
If an entry has no subcategories, but is a category which contains documents, nav.getChild(entry) will get the first document in that category.

Java IBM Lotus Notes retrive data from view fails in the middle due to null object

I am trying to retrieve data from lotus notes database view using a java program. Below is my code:
int resultsCount = view.getEntryCount();
print("Results found in view = " + resultsCount);
Document doc = view.getFirstDocument();
if (doc != null) {
int count = 1;
while (count <= resultsCount) {
count++;
try {
doc = view.getNextDocument(doc);
if (doc == null) {
print("Record " + count + " error. Null object.");
}
} catch (NotesException e) {
print("Record " + count + " error. Exception.");
}
}
}
else {
print("Record " + count + " error. Null object.");
}
I get below results:
Results found in view = 1567
Record 866 error. Null object.
Why is there a null document found when actually 1567 records present in the db view?
How can I resume to get rest of the records, because view.getNextDocument(doc) fails with Notes Exception after this happens.
Fixed by using
int resultsCount = view.getAllEntries().getCount();
instead of
int resultsCount = view.getEntryCount();
Using view.getAllEntries().getCount() returns the actual entry count which is 866. I am not sure what view.getEntryCount() returns. But it is definitely not the actual document count.
Edit:
As mentioned in XPages getEntryCount vs getAllEntries().getCount() view.getEntryCount() includes replications and save conflicts. Therefore to get actual record count needs to use view.getAllEntries().getCount()

Unable to delete a Node in jackrabbit

I am trying to delete a Node which I have saved using jackrabbit but I get this error.
Failed to delete file
! javax.jcr.nodetype.ConstraintViolationException: Unable to perform operation. Node is protected.
Here is the code I have used to save it:
session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
Node parent = (Node) itemAtPath(parentPath, session);
Node newNode = parent.addNode(nodeName);
newNode.addMixin("mix:versionable");
session.save(); // Create Root Node
VersionableChanges changes = new VersionableChanges(newNode.getSession());
changes.checkout(newNode);
Binary binary = session.getValueFactory().createBinary(in);
newNode.setProperty(PROPERTY_DATA, binary);
newNode.setProperty(PROPERTY_NAME, fileName + System.currentTimeMillis());
newNode.setProperty(PROPERTY_CREATEDBY, createdBy);
newNode.setProperty(PROPERTY_CREATEDDATE, createdDate);
newNode.setProperty(PROPERTY_COMMENT, comment);
Value value = session.getValueFactory().createValue(binary);
changes.checkin();
session.save();
Here is the code I am using to delete it:
session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
Version fileVersion = null;
Node fileNode = null;
if (version != null && !version.isEmpty()) {
fileVersion = session.getWorkspace().getVersionManager().getVersionHistory(path).getVersion(version);
} else {
fileVersion = session.getWorkspace().getVersionManager().getBaseVersion(path);
}
fileNode = fileVersion.getFrozenNode();
fileNode.remove();
//need to save session to persist the remove operation
session.save();
How can I overcome this error?
Frozen nodes are protected because deleting them would (maybe) put the version store in a corrupted state. In order to remove a "complete" version from the history, you have to something like this:
VersionHistory history = session.getWorkspace().getVersionManager()
.getVersionHistory(info.getVersionedNodePath());
history.removeVersion(info.getVersionName());
session.save();

List commits associated with a given tag with JGit

I need to create a history file that details all tags and for each tag, all its commits.
I've tried to call getTags() on the repository object and use those object id's, but they are not commit id's.
I also tried to use getAllRefsByPeeledObjectId() on the repository and that does bring back commits but I can't associate them to tags.
Any ideas?
List all Tags:
List<Ref> call = new Git(repository).tagList().call();
for (Ref ref : call) {
System.out.println("Tag: " + ref + " " + ref.getName() + " " + ref.getObjectId().getName());
}
List commits based on tag:
I'd use the log-command based on the tag-name with the peeled-magic as noted by Rüdiger:
LogCommand log = new Git(repository).log();
Ref peeledRef = repository.peel(ref);
if(peeledRef.getPeeledObjectId() != null) {
log.add(peeledRef.getPeeledObjectId());
} else {
log.add(ref.getObjectId());
}
Iterable<RevCommit> logs = log.call();
for (RevCommit rev : logs) {
System.out.println("Commit: " + rev /* + ", name: " + rev.getName() + ", id: " + rev.getId().getName() */);
}
See also my jgit-cookbook for some related examples.
To get a list of tags you can either use Repository#getTags() or the ListTagCommand.
There are annotated and unannotated tags in Git. While unannotated tags directly point to the commit they were placed on, an annotated tag points to a git object that holds - among other meta data like a message - the commit-id.
The learning test below ilustrates this:
public class TagLearningTest {
#Rule
public final TemporaryFolder tempFolder = new TemporaryFolder();
private Git git;
#Test
public void testUnannotatedTag() throws Exception {
RevCommit commit = git.commit().setMessage("Tag Me!").call();
Ref tagRef = git.tag().setAnnotated(false).setName("Unannotated_Tag").call();
assertEquals(commit.getId(), tagRef.getObjectId());
assertNull(git.getRepository().peel(tagRef).getPeeledObjectId());
}
#Test
public void testAnnotatedTag() throws Exception {
RevCommit commit = git.commit().setMessage("Tag Me!").call();
Ref tagRef = git.tag().setAnnotated(true).setName("Annotated_Tag").call();
assertEquals(commit, git.getRepository().peel(tagRef).getPeeledObjectId());
ObjectReader objectReader = git.getRepository().newObjectReader();
ObjectLoader objectLoader = objectReader.open(tagRef.getObjectId());
RevTag tag = RevTag.parse(objectLoader.getBytes());
objectReader.release();
assertEquals(commit.getId(), tag.getObject());
}
#Before
public void setUp() throws GitAPIException {
git = Git.init().setDirectory(tempFolder.getRoot()).call();
}
}
In JGit, an annotated tag is represented by a RevTag that is stored under the id to which the tag ref points to.
To tell one form the other, you can peel the ref and then test if its getPeeledObjectId() returns non-null.
Ref peeledRef = git.getRepository().peel( tagRef );
boolean annotatedTag = peeledRef.getPeeledObjectId() != null;
The peeled object id is the one that points to the commit on which the annotated tag was created.

Avoiding duplicate entries in a mongoDB with Java and JSON objects

I´m developing an analyzing program for Twitter Data.
I´m using mongoDB and at the moment. I try to write a Java program to get tweets from the Twitter API and put them in the database.
Getting the Tweets already works very well, but I have a problem when I want to put them in the database. As the Twitter API often returns just the same Tweets, I have to place some kind of index in the database.
First of all, I connect to the database and get the collection related to the search-term, or create this collection if this doesn´t exist.
public void connectdb(String keyword)
{
try {
// on constructor load initialize MongoDB and load collection
initMongoDB();
items = db.getCollection(keyword);
BasicDBObject index = new BasicDBObject("tweet_ID", 1);
items.ensureIndex(index);
} catch (MongoException ex) {
System.out.println("MongoException :" + ex.getMessage());
}
}
Then I get the tweets and put them in the database:
public void getTweetByQuery(boolean loadRecords, String keyword) {
if (cb != null) {
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
try {
Query query = new Query(keyword);
query.setCount(50);
QueryResult result;
result = twitter.search(query);
System.out.println("Getting Tweets...");
List<Status> tweets = result.getTweets();
for (Status tweet : tweets) {
BasicDBObject basicObj = new BasicDBObject();
basicObj.put("user_name", tweet.getUser().getScreenName());
basicObj.put("retweet_count", tweet.getRetweetCount());
basicObj.put("tweet_followers_count", tweet.getUser().getFollowersCount());
UserMentionEntity[] mentioned = tweet.getUserMentionEntities();
basicObj.put("tweet_mentioned_count", mentioned.length);
basicObj.put("tweet_ID", tweet.getId());
basicObj.put("tweet_text", tweet.getText());
if (mentioned.length > 0) {
// System.out.println("Mentioned length " + mentioned.length + " Mentioned: " + mentioned[0].getName());
}
try {
items.insert(basicObj);
} catch (Exception e) {
System.out.println("MongoDB Connection Error : " + e.getMessage());
loadMenu();
}
}
// Printing fetched records from DB.
if (loadRecords) {
getTweetsRecords();
}
} catch (TwitterException te) {
System.out.println("te.getErrorCode() " + te.getErrorCode());
System.out.println("te.getExceptionCode() " + te.getExceptionCode());
System.out.println("te.getStatusCode() " + te.getStatusCode());
if (te.getStatusCode() == 401) {
System.out.println("Twitter Error : \nAuthentication credentials (https://dev.twitter.com/pages/auth) were missing or incorrect.\nEnsure that you have set valid consumer key/secret, access token/secret, and the system clock is in sync.");
} else {
System.out.println("Twitter Error : " + te.getMessage());
}
loadMenu();
}
} else {
System.out.println("MongoDB is not Connected! Please check mongoDB intance running..");
}
}
But as I mentioned before, there are often the same tweets, and they have duplicates in the database.
I think the tweet_ID field is a good field for an index and should be unique in the collection.
Set the unique option on your index to have MongoDb enforce uniqueness:
items.ensureIndex(index, new BasicDBObject("unique", true));
Note that you'll need to manually drop the existing index and remove all duplicates or you won't be able to create the unique index.
This question is already answered but I would like to contribute a bit since MongoDB API 2.11 offers a method which receives unique option as a parameter:
public void ensureIndex(DBObject keys, String name, boolean unique)
A minor remind to someone who would like to store json documents on MongoDBNote is that uniqueness must be applied to a BasicObject key and not over values. For example:
BasicDBObject basicObj = new BasicDBObject();
basicObj.put("user_name", tweet.getUser().getScreenName());
basicObj.put("retweet_count", tweet.getRetweetCount());
basicObj.put("tweet_ID", tweet.getId());
basicObj.put("tweet_text", tweet.getText());
basicObj.put("a_json_text", "{"info_details":{"info_id":"1234"},"info_date":{"year":"2012"}, {"month":"12"}, {"day":"10"}}");
On this case, you can create unique index only to basic object keys:
BasicDBObject index = new BasicDBObject();
int directionOrder = 1;
index.put("tweet_ID", directionOrder);
boolean isUnique = true;
items.ensureIndex(index, "unique_tweet_ID", isUnique);
Any index regarding JSON value like "info_id" would not work since it´s not a BasicObject key.
Using indexes on MongDB is not as easy as it sounds. You may also check MongoDB docs for more details here Mongo Indexing Tutorials and Mongo Index Concepts. Direction order might be pretty important to understand once you need a composed index which is well explained here Why Direction order matter.

Categories

Resources