Sap and alfresco integrations with ctac connector 19 april2011
Alfresco Integrations - Alfresco Devcon 2012
-
Upload
jared-ottley -
Category
Technology
-
view
738 -
download
16
description
Transcript of Alfresco Integrations - Alfresco Devcon 2012
Alfresco Integrations: What We've Learned So Far
Jared OttleyIntegrations Engineer
Agenda
•State of the Union
•Projects
•Current Status•Jive Toolkit
•Dropbox
•Maven
•Google Docs•What's New
•oAuth Persistance
•Create Content Callback
•Evaluators, Custom Response
•oAuth
•Transaction Rollback Handling
•JMX
We've Grown
•Started with one Engineer - me!•Added a Project Manager - Peter Monks•Added another Engineer - Will Abson
Projects
•Google Docs v2 (Cloud, Enterprise, Community)
•Hyperic Plugin (Community)•Kofax (Enterprise)•XAM Connector (Enterprise)•S3 Connector (Cloud, Enterprise)•Salesforce (Cloud)•Jive Toolkit (Enterprise, Community)•Dropbox Connector (Community)
Projects (Cont.)
•Spring Social Dropbox (Fork)•Spring Social Google Docs•Spring Social AlfrescoContributed
•oAuth1/2 Persistence Service
•PDF Toolkit
•Share Extras
•Maven AMP Plugin
•Java CORS Filter
•Welsh Language Pack
Projects (Cont.)
•Share Import-Export Python scripts
•Ubuntu 'QuickStart' scripts
•WordPress Alfresco plugins
•Alfresco Community to Cloud Migration Utility
•And More....
What does the future hold?
The Future is Fluid
Jive Toolkit
What is it?A set of pre-built components that allows Jive to store documents in Alfresco while still offering all of the same social features as “native” Jive documents (commenting, rating, discussions, etc.)
Availability?Released Early 2012Current supported release version 1.0.5 for Alfresco 3.4.11
Support PortalCurrent community release version 1.1 for Alfresco 4.1
http://code.google.com/p/alfresco-jive-toolkit/
Jive Toolkit (Cont.)
Future?•The community project is looking for help.•SolutionSet is taking ownership of the project.•Looking for
o Developerso Testerso Users!o Documentation
Alfresco Dropbox Connector
What is it?The Alfresco Dropbox Connector allows a user to sync content/folders to their Dropbox Account. Content can be synced to multiple users accounts. When the content is updated in Alfresco it will be synced across all synced Dropbox Accounts. It supports manual updates back to Alfresco from Dropbox.
Availability?It is current available from Google Code (http://code.google.com/p/alfresco-dropbox-integration/). It is available as a community supported project. It requires at least Alfresco 4.1 (Enterprise) or 4.2 (Community)
Alfresco Dropbox Connector (Cont.)
Status?We are looking for Contributors, Testers, Documentation, Users.
What happened?Sync. Automatic sync between multiple sources is a complicated issue. It is even more complicated when one of the sources doesn't have a full understanding of content lifecycle....or managing it.
Alfresco Dropbox Connector (Cont.)
Issue 1: One to Many
Content in Alfresco is shared across multiple users but maintains a single source of truth.
When synced to Dropbox .... we have many sources.
Sharing content is explicit: a user has to initiate it. No API support.
Alfresco Dropbox Connector (Cont.)
Issue 2: Versioning
Dropbox has poor version support.•Revision created with each save•Revisions only available for the past 30 days•Revisions number are non sequential alphanumeric sequences•Modification dates can't be trusted
One to Many + Versioning = Nightmare.
Alfresco Dropbox Connector (Cont.)
Issue 3: File Changes (1)
Dropbox provides a delta api."A way of letting you keep up with changes to files and folders in a user's Dropbox. You can periodically call /delta to get a list of "delta entries", which are instructions on how to update your local state to match the server's state."
In reality, an entry in the delta list means the files is:...New...Update...Move...Copied...Renamed...an entry with no file metadata means the file has been
...Deleted...Moved...Renamed...
Alfresco Dropbox Connector (Cont.)
Issue 3: File Changes (2)
It is polling...
...which is expensive...
...which drains already costly resources...
Alfresco Dropbox Connector (Cont.)
Alfresco Dropbox Connector (Cont.)
Are we without options?No.
Our proposed approachOut of process polling
CMIS Client to AlfrescoRESTful client of DropboxComplicated ordering of content changes out of process
Maven
3.0.4 or 3.0.5-SNAPSHOT
Add to pom or settings.xml:
<pluginRepositories> <pluginRepository> <id>alfresco-public</id> <name>Alfresco</name> <url>https://artifacts.alfresco.com/nexus/content/repositories/releases</url> </pluginRepository> <pluginRepository> <id>alfresco-public-snapshots</id> <name>Alfresco</name> <url>https://artifacts.alfresco.com/nexus/content/groups/public-snapshots/</url> </pluginRepository> </pluginRepositories>
Maven
Alfresco dependencies can be found at
https://artifacts.alfresco.com
Add the amp packaging decleration to your pom.xml
<packaging>amp</packaging>
Maven
Repo/Share Pom
<plugin> <groupId>org.alfresco.maven.plugin</groupId> <artifactId>maven-amp-plugin</artifactId> <version>3.0.4</version> <extensions>true</extensions> <configuration> <mAmpJarExcludes>alfresco/module/**,alfresco/extension/**,alfresco/messages/**</mAmpJarExcludes> <!--exclude in share --> <archive> <addMavenDescriptor>false</addMavenDescriptor> </archive> </configuration> </plugin>
Maven
Share Pom (YUI Minification)
<plugin> <groupId>net.alchim31.maven</groupId> <artifactId>yuicompressor-maven-plugin</artifactId> <version>1.2</version> <executions><execution> <id>compressyui</id> <phase>process-resources</phase> <goals><goal>compress</goal></goals> </execution></executions> <configuration> <excludes> <exclude>**/*.css</exclude> <exclude>**/*.get.js</exclude> </excludes> </configuration></plugin>
Maven
├── module.properties├── pom.xml└── src
├── main│ ├── java│ │ └── org│ │ └── alfresco│ ├── resources│ │ └── alfresco│ │ ├── extension│ │ ├── messages│ │ └── module│ └── webapp│ └── WEB-INF│ └── web.xml└── test
├── java └── resources
Maven
Build command
mvn clean package [-DskipTests]
Amp location
in target directory
Validate amp content in directory of same name as amp (minus amp extension)
Google Docs V2
• Complete rewriteo Usabilityo Functionality
• No Shared Accounto Create and Edit content in their account
• Google is used as an editor, not persistance• Add-on not part of core• Cloud, Enterprise, Community
[Talk about Drive here :-)]
Google Docs V2
Demo
Google Docs V2
Google Docs V2
OAuth Credentials Store
Provide Token Persistence for oAuth1 and oAuth2Leverages Remote Credentials ServiceDropbox Integrations and Google Docs V2 this service
Google Docs V2
How To
private static OAuth2CredentialsStoreService oauth2CredentialsStoreService;
//Store Credentials. RemoteSystemId should be Uniqueoauth2CredentialsStoreService.storePersonalOAuth2Credentials(RemoteSystemId, AccessToken, RefreshToken, ExpiresAt, IssuedAt);
//Retrieve Credentials by RemoteSystemIdOAuth2CredentialsInfo oAuth2CredentialsInfo = oauth2CredentialsStoreService.getPersonalOAuth2Credentials(RemoteSystemId);
//Update Credentials the same way you add new ones...make sure the RemoteSystemId is the sameoauth2CredentialsStoreService.storePersonalOAuth2Credentials(RemoteSystemId, UpdatedAccessToken, UpdatedRefreshToken, UpdatedExpiresAt, UpdatedIssuedAt);
Google Docs V2
//Store Shared Credentials. Recomendation: Unqiue RemoteSystemIdoauth2CredentialsStoreService.storeSharedOAuth2Credentials(RemoteSystemId, AccessToken, RefreshToken, ExpiresAt, IssuedAt);
//Retrieve by RemoteSystemId Note: this returns a listList<OAuth2CredentialsInfo> sharedCredentials = oauth2CredentialsStoreService.listSharedOAuth2Credentials(RemoteSystemId);
//Update Share Credentials. Note the specifics method for updating shared credentialsoauth2CredentialsStoreService.updateSharedOAuth2Credentials(oAuth2CredentialsInfo, RemoteSystemId, UpdatedAccessToken, UpdatedRefreshToken, UpdatedExpiresAt, UpdatedIssuedAt);
Google Docs V2
//Delete Personal Credentials by RemoteSystemIdoauth2CredentialsStoreService.deletePersonalOAuth2Credentials(RemoteSystemId);
//Delete Share Credentials requires RemoteSystemId and the oAuth2CredentialsInfo instance of the specific credentialsList<OAuth2CredentialsInfo> sharedCredentials = oauth2CredentialsStoreService.listSharedOAuth2Credentials(RemoteSystemId); //find the ones you need in the list oauth2CredentialsStoreService.deleteSharedOAuth2Credentials(RemoteSystemId, oAuth2CredentialsInfo);
Google Docs V2
Create Content Action
Add to your share-config-custom.xml
<config evaluator="string-compare" condition="DocumentLibrary"> <create-content> <content id="google-docs" label="create-content.googledocs.document" icon="document" index="50" type="javascript"> <param name="function">onGoogledocsActionCreateDocument</param> </content> </create-content></config>
Google Docs V2
It supports 3 different actions: link, pagelink or javascript:
* "link" - accepts a "href" param that will be passed a nodeRef token for substitution, used for external links
* "pagelink" - accepts a "page" param that will be passed a nodeRef token for substitution, used for Share links
* "javascript" - accepts & "function" param of an action that will get the current folder item as first argument.
Evaluators are not currently supported, but permission checks are.
Google Docs V2
(function() {YAHOO.Bubbling.fire("registerAction", { actionName : "onGoogledocsActionCreateDocument", fn: function dlA_onGoogledocsActionCreateDocument(record) { //Do Work HerecreateGoogleDoc.call(this, record, "document"); }})})();
Google Docs V2
DocLib Actions: Evaluators, Custom ResponsesTwo actions:
Edit ContentResume Editing Content
Edit ContentOnly a specific set of content can be edited by Google DocsContent that is currently being edited can't be "edited"User must have write access to the nodeDocument Size LimitsGoogle Docs Service can be turned off
Google Docs V2
Editing Action
<action id="google-docs-edit-action-link" type="javascript" icon="google-edit" label="googledocs.actions.edit"> <param name="function">onGoogledocsActionEdit</param> </action>
JavaScript or PageLink?
Debugging
http://localhost:8080/alfresco/service/slingshot/doclib2/node/workspace/SpacesStore/8759ce08-acaa-4d69-807e-23c98a53fd17
Google Docs V2
User must have write access to the node
<permissions> <permission allow="true">Write</permission> </permissions>
Possible Permissions
CancelCheckOut ChangePermissions CreateChildren Delete Write
Google Docs V2
Content that is currently being edited can't be "edited"
Content being edited has the gd2:editingInGoogle aspect applied
<bean id="evaluator.doclib.google.docs.doesnothaveaspect" parent="evaluator.doclib.metadata.doesNotHaveAspect"> <property name="aspects"> <list> <value>gd2:editingInGoogle</value> </list> </property>
<property name="negateOutput" value="true" /> </bean>
Google Docs V2
Document Size Limits
Google Docs has a complex set of sizes (http://support.google.com/drive/bin/answer.py?hl=en&answer=37603)
<bean id="evaluator.doclib.metadata.sizeLimit" class="org.alfresco.integrations.web.evaluator.SizeLimitEvaluator"> <property name="maxDocumentSize" value="2097152"/> <property name="maxSpreadsheetSize" value="20971520"/> <property name="maxPresentationSize" value="52428800"/> </bean>
Google Docs V2
Remember!
Numeric values in json are doubles.
long size = ((Double)node.get("size")).longValue();String contentType = getContentType(node.get("mimetype").toString());
if (contentType == null || size > getMaxFileSize(contentType)){ return false;}
Google Docs V2
Only a specific set of content can be edited by Google Docs
application/vnd.openxmlformats-officedocument.presentationml.presentationapplication/vnd.ms-powerpointtext/tab-separated-valuesapplication/vnd.sun.xml.writerapplication/vnd.ms-excelapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetapplication/rtfapplication/mswordapplication/vnd.oasis.opendocument.texttext/plaintext/csvapplication/x-vnd.oasis.opendocument.spreadsheetapplication/vnd.oasis.opendocument.spreadsheet <!-- GOOGLEDOCS-71 -->application/vnd.openxmlformats-officedocument.wordprocessingml.document
Google Docs V2
<property name="importFormats"> <map> <entrykey="application/vnd.openxmlformats-officedocument.presentationml.presentation"> <value>presentation</value> </entry>....
</map></property
Google Docs V2
<property name="exportFormats"> <map> <entry key="document"> <map> <entry key="application/vnd.openxmlformats-officedocument.wordprocessingml.document"> <value>docx</value> </entry>
...</map></entry>
</map></property>
Google Docs V2
Bonus
application/x-msmetafile
Google Docs V2
<bean id="evaluator.doclib.metadata.isMimetype" class="org.alfresco.integrations.web.evaluator.IsMimetypeEvaluator"/>
<bean id="evaluator.doclib.google.docs.mimetype" parent="evaluator.doclib.metadata.isMimetype"> <property name="mimetypes" value="custom.googledocs.importFormats"/> </bean>
Google Docs V2
Google Docs Service can be turned off
googledocs.enabled=true
public Serializable populate(){
Map<String, Serializable> map = new LinkedHashMap<String, Serializable>(2); map.put("enabled", (Serializable)googledocsService.isEnabled()); map.put("importFormats", (Serializable)googledocsService.getImportFormats());
return (Serializable)map;}
Google Docs V2
<bean id="evaluator.doclib.google.docs.enabled" parent="evaluator.doclib.action.metadataValue"> <property name="accessor" value="custom.googledocs.enabled"/> <property name="comparator"> <bean class="org.alfresco.web.evaluator.StringEqualsComparator"> <property name="value" value="true" /> </bean> </property>
Google Docs V2
Chaining our Evaluators
Edit Evaluator <bean id="evaluator.doclib.google.docs.edit" parent="evaluator.doclib.action.chainedMatchAll"> <property name="evaluators"> <list> <ref bean="evaluator.doclib.google.docs.enabled"/> <ref bean="evaluator.doclib.google.docs.mimetype" /> <ref bean="evaluator.doclib.google.docs.doesnothaveaspect" /> <ref bean="evaluator.doclib.google.docs.maxsize" /> </list> </property> </bean>
Google Docs V2
<bean id="evaluator.doclib.google.docs.resume" parent="evaluator.doclib.action.chainedMatchAll"> <property name="evaluators"> <list> <ref bean="evaluator.doclib.google.docs.aspect"/> <ref bean="evaluator.doclib.indicator.lockOwner"/> </list> </property> </bean>
Resume Edit Evaluator
Google Docs V2
OAuth WorkflowAuthentication is a challenge no matter what the authentication type.
oAuth is only part of the solution for Google Docs...but we leverage it to solve other issues as well
We leveraged our own spring-social-google-docs.spring-social-google was not compatiblespring-social-google-docs is a wrapper for gdataNewer google client did not provide a client api for Google Docs
Google Docs V2
Google Docs V2
ComponentsTwo Web Scripts
1. Provides the Authentication URL2. Completes the Authentication
-Persists the Tokens
Client Side JSInitiate the Flow
Calls to RepoOpens ModalDialog or new Window
Secret Sauce: Callback page, browser redirect the auth token to repo
Google Docs V2
Rollback Callback
Used to handle additional clean up work when a transaction is rolled back. Could be used to perform work in another system or in Alfresco.
Clean up NotificationsSome Unit of Work
Google Docs V2
catch (SomeException e) { AlfrescoTransactionSupport.bindListener(new TransactionListenerAdapter() { public void afterRollback() { transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Object>() { public Object execute() throws Throwable {
//do work here }
}, false, true); } }); //Something maybe needed here like throw new SomeOtherException(e.getMessage(), e); }
Google Docs V2
JMX
Any properties you add to for your custom beans to pick up are made read-only in JMX. If you want read write, make a subsystem.
Define your ChildApplicationContextFactory bean in your AMPs module.properties file.
Create a directory structure in your resource directoryalfresco.subsystems.<category>[.<instance>]
Add your systems <name>-context.xml and <name>.properties files
Google Docs V2
<bean id="googledocs_v2" class="org.alfresco.repo.management.subsystems.ChildApplicationContextFactory" parent="abstractPropertyBackedBean"> <property name="category"> <value>googledocs</value> </property> <property name="typeName"> <value>v2</value> </property> <property name="instancePath"> <value>v2</value> </property> <property name="autoStart"> <value>true</value> </property> </bean>
Google Docs V2
Best PracticesKeep your model in you subsystem. Web Scripts Cannot be defined in your subsystemTest what happens when you unload your subsystem
--Subsystems can be automatically reloaded--If you don't want that to happen,
Add programmatic controls to keep its beans from being called