Properties from aspects not set in CMIS 1.1 - alfresco

We have a problem with a Folder object and custom aspects:
...
properties.put(PropertyIds.OBJECT_TYPE_ID, "F:sd:folderDocument,P:sd:info");
properties.put("sd:cause", "asdfg");
Folder stDocument = folder.createFolder(properties);
...
Conten of sd:cause is "nothing" in CMIS 1.1 but in CMIS 1.0 work fine.
NOT WORK!
params.put(SessionParameter.ATOMPUB_URL, "http://localhost:8084/alfresco/api/-default-/public/cmis/versions/1.1/atom");
WORK!
params.put(SessionParameter.ATOMPUB_URL, "http://localhost:8084/alfresco/api/-default-/public/cmis/versions/1.0/atom");
We need work in version 1.1

In CMIS 1.1 you add an aspect by adding the aspect type ID to the cmis:secondaryObjectTypeIds property. Here is an example: https://gist.github.com/jpotts/7242070
Make sure you are NOT using the alfresco object factory from the CMIS extensions project when using CMIS 1.1.

The unit test with cmis:secondaryObjectTypeIds is:
#Test
public void createStDocumentWithCMIS11() {
String folderId = "workspace://SpacesStore/03de40f1-e80d-4e0d-8b67-67e93f6e30a1";
// Connection and session to CMIS 1.1
HashMap<String, String> params = new HashMap<>();
params.put(SessionParameter.ATOMPUB_URL, "http://localhost:8084/alfresco/api/-default-/cmis/versions/1.1/atom");
params.put(SessionParameter.USER, "admin");
params.put(SessionParameter.PASSWORD, "admin");
params.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
params.put(SessionParameter.OBJECT_FACTORY_CLASS, "org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl");
SessionFactory factory = SessionFactoryImpl.newInstance();
Session session = factory.getRepositories(params).get(0).createSession();
// Find root folder
Folder folder = (Folder) session.getObject(folderId);
assertNotNull(folder);
// Properties for type
Map<String, Object> properties = new HashMap<>();
properties.put(PropertyIds.NAME, "Test CMIS folder type stDocument");
properties.put(PropertyIds.OBJECT_TYPE_ID, "F:sd:structDocument");
properties.put("sd:situation", "situation");
// Create folder
Folder stDocument = folder.createFolder(properties);
assertNotNull(stDocument);
// Add secondary objects (Aspects)
List<Object> aspects = stDocument.getProperty("cmis:secondaryObjectTypeIds").getValues();
aspects.add("P:sd:additionalInfo");
HashMap<String, Object> props = new HashMap<>();
props.put("cmis:secondaryObjectTypeIds", aspects);
stDocument.updateProperties(props);
// Add aspect's property
HashMap<String, Object> propsAspects = new HashMap<>();
propsAspects.put("sd:cause", "test");
stDocument.updateProperties(propsAspects);
assertEquals("test", stDocument.getProperty("sd:cause").getValueAsString());
}
But not work... :(

Related

How to access document on alfresco?

I created a project alfresco amp.
To add a document, I run this Test class:
public class Test {
public static void main(String[] args) throws UnsupportedEncodingException {
Map<String, String> sessionParameters = new HashMap<String, String>();
sessionParameters.put(SessionParameter.USER, "admin");
sessionParameters.put(SessionParameter.PASSWORD, "admin");
sessionParameters.put(SessionParameter.ATOMPUB_URL, "http://localhost:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom");
sessionParameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
SessionFactory sessionFactory = SessionFactoryImpl.newInstance();
Session lSession = sessionFactory.getRepositories(sessionParameters).get(0).createSession();
Folder root = lSession.getRootFolder();
Map<String, Object> folderProperties = new HashMap<String, Object>();
folderProperties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder");
folderProperties.put(PropertyIds.NAME, "oo");
Folder newFolder = root.createFolder(folderProperties);
Map<String, Object> lProperties = new HashMap<String, Object>();
String name = "lol.txt";
lProperties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");
lProperties.put(PropertyIds.NAME, name);
byte[] content = "CMIS Testdata One".getBytes();
InputStream stream = new ByteArrayInputStream(content);
ContentStream contentStream = new ContentStreamImpl(name, new BigInteger(content), "text/plain", stream);
Document newContent1 = newFolder.createDocument(lProperties, contentStream, null);
System.out.println("Document created: " + newContent1.getId());
}
}
The document is created with success; I got: Document created: e3184105-e59e-4b8a-88e7-9442942433a4;1.0
My problem is how can I access to this document (With which url can I access to that document).
Please help?.
It looks like you've created a document and you now want to know what URL to use to get to it. You have many options, some of which include...
Use the Alfresco web app's download URL:
http://localhost:8080/alfresco/s/api/node/workspace/SpacesStore/dac36aab-dd49-4abc-a4bc-0e0d5729c9ad/content;cm%3Acontent
Use the Share web app's download URL:
http://localhost:8080/share/proxy/alfresco/slingshot/node/content/workspace/SpacesStore/dac36aab-dd49-4abc-a4bc-0e0d5729c9ad/test.txt
Use the CMIS URL (AtomPub binding):
http://localhost:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom/content/test.txt?id=dac36aab-dd49-4abc-a4bc-0e0d5729c9ad%3B1.0
Use the CMIS URL (Browser binding):
http://localhost:8080/alfresco/api/-default-/public/cmis/versions/1.1/browser/root?objectId=dac36aab-dd49-4abc-a4bc-0e0d5729c9ad%3B1.0&cmisselector=content
Write your own URL handler that fetches the input stream via CMIS and returns that stream to the requester. Assuming you are using something like Spring MVC, the code for that might look like:
public InputStream download(String objectId) {
Session session = getSession();
CmisObject obj = session.getObject(objectId);
Document doc = null;
if (obj.getBaseTypeId().equals(BaseTypeId.CMIS_DOCUMENT)) {
doc = (Document) obj;
}
return doc.getContentStream().getStream();
}
Each of the above options assumes a test file in a test folder named "test.txt" with an Alfresco Node Reference of:
workspace://SpacesStore/dac36aab-dd49-4abc-a4bc-0e0d5729c9ad
And a CMIS Object ID of:
dac36aab-dd49-4abc-a4bc-0e0d5729c9ad;1.0

Alfresco can I Change properties "cmis:creationDate and cmis:lastModificationDate" Updatablity?

Hi and thanks in advance for the help
I have a problem with insertion and update documents in alfresco, So when I set a property like "cmis:creationDate or cmis:lastModificationDate", the document is created successfully but the properties that has Updatability=ReadOnly doesn't set to the new value given it's set automatically by alfresco.
Is there any solution to set Updatibility of these properties to "ReadWrite"?
I'm using Aalfresco 5.0 and openCmis 0.13 this is my code :
public void createDocument(Folder folder) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date d = sdf.parse("21/12/2012");
String name = "myNewDocument.txt";
Map<String, Object> properties = new HashMap<String, Object>();
Calendar cal = new GregorianCalendar();
cal.setTime(d);
properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document,P:cm:titled,P:cm:author");
properties.put(PropertyIds.NAME, name);
properties.put(PropertyIds.CREATION_DATE, cal);
properties.put(PropertyIds.LAST_MODIFICATION_DATE, cal);
properties.put("cm:title", "Title");
properties.put("cm:description", "Description");
properties.put("cm:author", "author");
properties.put("cmis:creationDate ", cal);
byte[] content = "Hello World!".getBytes();
InputStream stream = new ByteArrayInputStream(content);
ContentStream contentStream = new ContentStreamImpl(name, BigInteger.valueOf(content.length), "text/plain", stream);
Document newDoc = folder.createDocument(properties, contentStream, VersioningState.MAJOR);
}
Updating the read only fields requires work on the Alfresco side. There are policies in place that prevent properties of the aspect cm:auditable from being changed.
You can update the fields in Alfresco using the NodeService API after you've disabled that policy behavior. Here's an example:
policyBehaviourFilter.disableBehaviour(node, ContentModel.ASPECT_AUDITABLE);
// Update CreatedDate
nodeService.setProperty(node, ContentModel.PROP_CREATED, dateTime);
//Enable policy
policyBehaviourFilter.enableBehaviour(node, ContentModel.ASPECT_AUDITABLE);
You could package this into a custom webscript to allow the properties to be changed remotely.

How to get Html of any view by it's full file location

public string GetRazorViewAsString(string filePath, object model = null)
{
var resultString = new StringWriter();
var context = new HttpContextWrapper(HttpContext.Current);
var routeData = new RouteData();
// Creatign the controller context
var controllerContext = new ControllerContext(new RequestContext(context, routeData), new DummyController());
// Rebdering the view and getting the html to resultString
var razor = new RazorView(controllerContext, filePath, null, false, null);
razor.Render(new ViewContext(controllerContext, razor, new ViewDataDictionary(model), new TempDataDictionary(), resultString), resultString);
// Returning the generated html
return resultString.ToString();
}
public class DummyController : Controller { }
Currently, we are using above code for generating HTML for a view.
In that, view path is a virtual path.
Now, we are planning to move the views outside of the project. So keeping virtual path is not possible now.
Is there any way of creating HTML by taking full path of the view
You can implement a VirtualPathProvider. Create a class that inherits from VirtualPathProvider, then override two methods:
FileExists
GetFile
These methods accept a virtual path argument, which you can then map to some location on disk. Your controllers will be unaware that this provider exists (they continue to use virtual paths for views). You may need to also implement a VirtualFile.
For more information, see http://www.umbraworks.net/bl0g/rebuildall/2009/11/17/ASP_NET_MVC_and_virtual_views. This blog post is sourcing views from a database, but you can adapt it to source views from anywhere.

How to configure custom aspects and retrieve its property using CMIS 1.1 atom binding alfresco 5.0.c?

Using Alfresco, I have created an aspect and added custom properties to it.
Need help in accessing the custom properties using CMIS 1.1 Atom Binding and Alfresco 5.0.c.
Kindly help me to display the document with its custom properties.
public void uploadDocument(Folder newFolder) {
File file = new File("file.txt");
properties = new HashMap<String, Object>();
properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");
properties.put(PropertyIds.NAME, file.getName());
properties.put(PropertyIds.CUSTOM_FIELD_NAME,file.getCustomField());
path = Paths.get(DOC_NAME_WITH_PATH);
content= Files.readAllBytes(path);
contentStream = new ContentStreamImpl(file.getName(),
BigInteger.valueOf(content.length), new
MimetypesFileTypeMap().getContentType(file), new
FileInputStream(file));
newDoc = (Document)newFolder.createDocument(properties, contentStream,
VersioningState.MAJOR);
}

NVelocity ASP.NET Examples

I'm looking to use NVelocity in my ASP.NET MVC application, not as a view engine, just for rendering some email templates.
However, I cannot for the life of me get it to work. I have downloaded it from the castle project and followed the example at http://www.castleproject.org/others/nvelocity/usingit.html#step1
No matter what I try I don't seem to be able to load a template located in my site. The example suggests using the absolute path, which I have tried to no avail:
Template t = engine.GetTemplate("/Templates/TestEmail.vm");
So please can someone give me two examples. One of loading a template located in the web site directory and secondly one parsing a string variable (as it is likely that my templates will be stored in a database).
Many thanks
Ben
I've used this class in one of my past projects:
public interface ITemplateRepository
{
string RenderTemplate(string templateName, IDictionary<string, object> data);
string RenderTemplate(string masterPage, string templateName, IDictionary<string, object> data);
}
public class NVelocityTemplateRepository : ITemplateRepository
{
private readonly string _templatesPath;
public NVelocityTemplateRepository(string templatesPath)
{
_templatesPath = templatesPath;
}
public string RenderTemplate(string templateName, IDictionary<string, object> data)
{
return RenderTemplate(null, templateName, data);
}
public string RenderTemplate(string masterPage, string templateName, IDictionary<string, object> data)
{
if (string.IsNullOrEmpty(templateName))
{
throw new ArgumentException("The \"templateName\" parameter must be specified", "templateName");
}
var name = !string.IsNullOrEmpty(masterPage)
? masterPage : templateName;
var engine = new VelocityEngine();
var props = new ExtendedProperties();
props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, _templatesPath);
engine.Init(props);
var template = engine.GetTemplate(name);
template.Encoding = Encoding.UTF8.BodyName;
var context = new VelocityContext();
var templateData = data ?? new Dictionary<string, object>();
foreach (var key in templateData.Keys)
{
context.Put(key, templateData[key]);
}
if (!string.IsNullOrEmpty(masterPage))
{
context.Put("childContent", templateName);
}
using (var writer = new StringWriter())
{
engine.MergeTemplate(name, context, writer);
return writer.GetStringBuilder().ToString();
}
}
}
In order to instantiate the NVelocityTemplateRepository class you need to provide an absolute path where your templates root is. Then you use relative paths to reference your vm files.
I also added the following method to process a string instead of a template file (say if retrieving the template content from a database):
public string RenderTemplateContent(string templateContent, IDictionary<string, object> data)
{
if (string.IsNullOrEmpty(templateContent))
throw new ArgumentException("Template content cannot be null", "templateContent");
var engine = new VelocityEngine();
engine.Init();
var context = GetContext(data);
using (var writer = new StringWriter()) {
engine.Evaluate(context, writer, "", templateContent);
return writer.GetStringBuilder().ToString();
}
}
And used StructureMap to initialize the service:
ForRequestedType<ITemplateService>()
.TheDefault.Is.ConstructedBy(()=>
new NVelocityTemplateService(HttpContext.Current.Server.MapPath("~/Content/Templates/")));
You might find the TemplateEngine component useful.
It's an abstraction over template engines with a NVelocity implementation, similar to Darin's answer, but it should perform marginally better since it uses a single instance of the VelocityEngine (as opposed to initializing one instance per render) and has optional caching. It also has a couple other features, like logging, NVelocity property overriding and loading templates from assembly resources.

Resources