Unable to Unlock Alfresco Document using CMIS - alfresco

I'm using CMIS to make changes to alfresco document, I need to add new aspect to document, but I'm facing:
org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException: Update conflict: 06160811 Cannot perform operation since the node (id:88289ea7-16b7-40ff-938b-b2888ef5bca5) is locked.
Below is the code I'm trying to unlock the document, but it's not successful. kindly suggest other alternatives to unlock a locked document using CMIS
for (QueryResult result : results) {
String objectId = result.getPropertyValueByQueryName(PropertyIds.OBJECT_ID);
AlfrescoDocument document = (AlfrescoDocument) session.getObject(session.createObjectId(objectId));
if (document != null) {
if(document.hasAspect("P:cm:lockable")) {
System.out.println(document.getName());
document.removeAspect("P:cm:lockable");
}
} else {
System.out.println("Document is null");
}
}

What version of Alfresco and CMIS are you using? It looks like you might be using the Alfresco CMIS extension JAR, but you should not be using that at all if you are using Alfresco 5.2 (or higher) and CMIS 1.1.
If you are using CMIS 1.1, the way to remove an aspect is to remove the name of the aspect from the array of values in the cmis:secondaryObjectTypeIds array, then update the properties with the trimmed list of aspects.
With all of that said, that would just remove the lockable aspect from the document. You are trying to actually unlock the document, not remove its ability to be locked/unlocked. So instead of trying to directly manipulate the aspect, you should just call cancelCheckout() if you want to unlock the document, like:
Document doc = (Document) getSession().getObjectByPath(filePath);
doc.cancelCheckOut();
Obviously you'll need to use credentials of someone who has the permissions to do this.

Use LockService.
lockService.unlock("nodeRef of the node to unlock")

Related

Upload a newer version of document from within Alfresco repository

I have a two documents (a.pdf and b.pdf) in the Alfresco repository. I want to apply/upload b.pdf as a new version of a.pdf. Is there any way that I can do this using Javascript or a java code?
Thank you
Create Document, Make it Versionable, Modify It
Creates a document, makes it versionable, checks it out, modifies the content of the working copy, checks it in again and then repeats the process but checks in the document with a version history note and as a major version increment:
// create file, make it versionable
var doc = userhome.createFile('checkmeout.txt');
doc.addAspect('cm:versionable');
doc.content = 'original text';
// check it out and update content on the working copy
var workingCopy = doc.checkout();
workingCopy.content = 'updated text 1';
// check it in
doc = workingCopy.checkin();
// check it out again
workingCopy = doc.checkout();
workingCopy.content = 'updated text 2';
// check it in again, but with a version history note and as major version increment
doc = workingCopy.checkin('a history note', true);
You can take reference from below javascript api link
https://hub.alfresco.com/t5/alfresco-content-services-hub/javascript-api-cookbook/ba-p/293260
There's a version service bean that can be used to apply versioning to documents (nodes) that can be used in a custom bean. Don't forget to inject the versionService in your service-context.xml btw <property name="versionService" ref="VersionService"/>
If I remember correctly you may have to enable a versionable aspect (cm:versionable) on the node in question. If this has already been enabled then there's also the ability to view the VersionHistory for the node.
Create 2nd version and copy over with the contents of node 2.

find alfresco nodeRef without using luceneSearch

I have a js webscript who return a list of documents from a specific repository in Alfresco. i used the luceneSearch to get the nodeRef of the repository, this works fine.
The repository primary path is: /app:company_home/app:dictionary/cm:StarXpert_x0020_Workflow/cm:fichiers_x0020_JSON and i used the luceneSearch like this to get the nodeRef from the primary path
var nodes = search.luceneSearch("PATH:\"/app:company_home/app:dictionary/cm:StarXpert_x0020_Workflow/cm:fichiers_x0020_JSON//*\" AND TYPE:\"cm:content\"","#cm:name", true);
But when i execute my code in the server side, i have an error, that my webScript can't get the nodes from the path i took it. I searched and i found that the problem is an indexation problem on the server alfresco version.
So my question is: can us get a nodeRef from a primary path, whithout using luceneSearch?
Thanks for any help
If I understand the documentation, you can use other methods with the search root object. The xpathSearch seems interesting :
org.mozilla.javascript.Scriptable xpathSearch(String search)
Execute a XPath search
The selectNodes(String search) might be interesting too.

How to get Aspect specific properties using Open CMIS

I am doing content migration activity. in that i am able to migrate actual content from one repository to other. but i also want to migrate meta-date for same.
I have some aspect's associated with my content and every aspect is having some properties. So i want to get those aspect specific properties from old repository. but i am not finding any useful code to get aspect properties. I am able to add aspect and properties in new repository.
AlfrescoDocument alfDoc = (AlfrescoDocument) dc;
alfDoc.addAspect("P:test:publishDate");
if (alfDoc.hasAspect("P:test:publishDate")) {
Map<String, GregorianCalendar> properties1 = new HashMap<String, GregorianCalendar>();
properties1.put("test:pubDate", dc.getCreationDate());
alfDoc.updateProperties(properties1);
}
But in same way i want to fetch aspect specific properties from old repository. Can anyone please help me.
Thanks in Advance.
There is an answer here, this might relate to your question?
https://community.alfresco.com/thread/201527-not-able-to-read-aspect-properties-using-cmis
Basically, make sure to use the proper CMIS 1.1 service URL http://localhost:8080/alfresco/api/-default-/public/cmis/versions/1.1/browser
Then something like this:
ItemIterable<QueryResult> queryResults = cmisSession.query(cmisQuery, false);
for (QueryResult queryResult:queryResults) {
PropertyData<?> abcProperty = queryResult.getPropertyById("abc");
String abcValue = abcProperty.getFirstValue().toString()
//…
}

Updating GridFS metadata using Spring Data MongoDB

I want to update single field of metadata in GrifFs files collection.
I read the documentation about Spring Data MongoDB but did not find any API for that.
The only solution I have found so far is to use the Mongo API directly to delete the existing file, and store a new one with the same _id. But this is not effective solution. The problem is specific to Spring Data MongoDB . any alternative ?
use mongoOperations.
the metadata is stored in the collection fs.files; if you are only updating the metadata you can access it by using the collection directly and update it:
DBObject yourObjectWithMetadata = mongoOperations.getCollection("fs.files").findOne(<Object Id>);
mongoOperations.getCollection("fs.files").save(<your db object with updated metadata>);
Another solution to add or entirely replace metadata fields.
Map<String,Object> fields=...;
Replacing metadata:
List<GridFSDBFile> files = gfs.find(query);
for (GridFSDBFile file : files) {
file.setMetaData(new BasicDBObject(fields));
file.save();
}
Adding metadata:
List<GridFSDBFile> files = gfs.find(query);
for (GridFSDBFile file : files) {
if (file.getMetaData() == null)
file.setMetaData(new BasicDBObject(fields));
else
file.getMetaData().putAll(fields);
file.save();
}

ASP.Net How to access images from different applications

I have 2 different project. One is supposed to upload images (admin) and the other is supposed to show them.
I was writing something like "/Contents/images/image path"... But wait! I will I upload the images from the application into that address?
Any help and suggestions please.
If you have two applications that will interact with the same files, it's probably better to have an ImageController with an action that allows you to upload/download the image rather than storing them directly as content. That way both applications can reference the same file location or images stored in a database and manipulate them. Your download action would simply use a FileContentResult to deliver the bytes from the file. You can derive the content type from the file extension.
Example using a database. Note that I assume that the database table contains the content type as determined at upload time. You could also use a hybrid approach that stores the image metadata in a database and loads the actual file from a file store.
public class ImageController : Controller
{
public ActionResult Get( int id )
{
var context = new MyDataContext();
var image = context.Images.SingleOrDefault( i => i.ID == id );
if (image != null)
{
return File( image.Content, image.ContentType );
}
// or you could return a placeholder image here if appropriate.
throw new HttpException( 404, "The image does not exist" );
}
}
An alternative would be to incorporate your administrative interface in an area of the same application rather than in a separate project. This way you could reuse the content/images directory if you wanted. I find that when you have dynamic images the database or a hybrid approach works better from a programming perspective since it's more consistent with the rest of your data model.
you could try like this..
Let's assume that all of your images are in Project A and you want to use the same images in Project B.
Open Project B with Visual Studio. In the Solution Explorer, right click your Project Name and select "Add Existing Item...".
Browse to the physical location on disc where your images in Project A are stored and select the files that you want to import.
You'll then be able to access those images from project A in Project B.

Resources