Quantcast
Viewing all 161 articles
Browse latest View live

Introducing Our New Open Source Box API

This week, Nuxeo announced a new API for file sharing and storage called the “Box API for the Nuxeo Platform”. To give you a better picture of what this new API is and why it was built, I talked to Thierry Delprat, Nuxeo CTO.

What is the Box API for the Nuxeo Platform?

Thierry told me that this is a REST API that, initially, is meant to share and store files. It is an open source implementation of the Box API that runs on top of a Nuxeo repository.

The Box API for the Nuxeo Platform implements a subset of the Box API, including: Folders, Files, Collaboration and Search, with Comments coming soon.

The intent of the open source project is to implement the entire Box API. Thierry said they are looking forward to working with other developers on this project to increase its coverage and strengthen the code. He also indicated that it would be great to see other vendors use this connector.

Why did Nuxeo decide to launch this project?

In their work with customer development teams, Nuxeo saw some building small web apps or mobile apps using the Box API. While, overall, they were satisfied with that API, they did have issues with testability and some wanted to go further in terms of features.

Nuxeo sees Box as the clear leader of content collaboration in the Cloud. It certainly surpasses SharePoint and Office 365 SharePoint, and offers more functionality than DropBox. As more developers use the Box API to build content collaboration apps – especially mobile apps – it’s clear that Box has something good happening.

Along with application testing challenges for developers, there are instances where using the Box public cloud infrastructure won’t work, due to compliance or security issues.

With this open source project, Thierry said that Nuxeo wanted to help developers create Box applications by:

  1. Giving them a way to run “their own local Box server” using the Nuxeo Platform. This allows developers to run a Box server locally, in a continuous integration chain.
  2. Opening up the opportunity for developers to serve customers with on premises requirements (or different cloud infrastructures).

Essentially, Nuxeo wants to support Box and help it become the industry standard for content collaboration in the Cloud, by helping to broaden its reach and opening the door for more opportunities.

Image may be NSFW.
Clik here to view.
Sample of Box API for the Nuxeo Platform

Sample of Box API for the Nuxeo Platform

How do you see the Box API for the Nuxeo Platform being used?

Thierry says that there are two primary uses cases for the Box API for the Nuxeo Platform, although he’s sure the community will come up with more once they start using it.

1. Test out of the Box

One of the big challenges with the Box API is that there is no way to test that an app is running correctly and will continue to do so. Developers need automatic testing.

If a developer uses the Box API for unit and integration testing, then they have to use a real Box account. Doing this could be difficult for a few reasons:

  • It could cause performance issues,
  • It could result in additional billing, and
  • There might be trouble debugging.

Instead, a developer could use the Nuxeo Platform and easily run tests without any issues. All they have to do is install a Nuxeo server (which is free and very simple to do), then install Nuxeo’s Box API connector which exposes the Nuxeo server in place of the Box server.

The application can continue to talk Box protocol and Nuxeo understands that protocol. Test the application, make any changes required and it should be good to implement the real thing.

2. Own your own Box

It may be that the organization likes the functionality available in Box, but isn’t able to run in a cloud environment – maybe it’s a compliance or confidentiality issue, or simply a bandwidth problem. The Box API for the Nuxeo Platform lets these organizations bring the power of Box on premises.

Note that this is also a great solution to backup a Box account, or to offer a hybrid content management solution where content is stored within Box and on premises (both Nuxeo and Box support OAuth 2 for authentication).

Implementing the Nuxeo server and the Box API connector also simplifies the set up of development environments, Thierry said. Instead of trying to configure CORS for multiple developer test domains against the Box server, each developer has his/her own instance of a Nuxeo server to configure for testing, with no impact to the production server.

Helping Box Applications Support More Use Cases

Thierry is quick to point out that this open source implementation of the Box API isn’t competition for Box. Box has the potential for its API to become the defacto standard for content management in the cloud, and having an open source implementation of it is extremely useful. Nuxeo’s goal, said Thierry, is to simply support new use cases in the Box ecosystem, enabling developers to continue to build great web and mobile applications.

Box is a cloud-based solution whereas the Nuxeo Platform can be run on any infrastructure (on premises or in the Cloud). By connecting the two platforms with the Box API for the Nuxeo Platform, developers can design and build solutions that work both in the cloud and on premises. According to Thierry, it’s a win-win for Box and app developers.

What are the next steps for the Box API Connector?

Never one to build and walk away, I asked Thierry what the next steps are now that the Box API for the Nuxeo Platform is available.

Thierry said they wanted to see if there was interest within the community. If the feedback is good and they see developers interested in moving the project forward, they’ll continue to implement a wider portion of the Box API.

Said Thierry:

As with pretty much everything we do at Nuxeo, the Box API for the Nuxeo Platform is fully open source. If you feel like making it better, fork it and send us pull requests – we like that!”

Learn more about the Box API for the Nuxeo Platform, get it from the Nuxeo Marketplace or jump right to GitHub and download it now.

The post Introducing Our New Open Source Box API appeared first on Nuxeo Blogs.


The Nuxeo Roadmap on www.nuxeo.com

Image may be NSFW.
Clik here to view.
NuxeoRoadmap

The Nuxeo roadmap is now available on nuxeo.com.

You can see the main items that are scheduled for each fast track, each with a short description. Green is for a released fast track version, blue is the next one to be released and orange is for upcoming versions.

Along with brief descriptions of items in the roadmap, you should also notice small icons on the top-right corner of each item that offers shortcuts to additional information. Other uses of the roadmap page include:

Image may be NSFW.
Clik here to view.
Screen Shot 2014-03-24 at 14.40.31

  • View dates of all the scheduled releases.
  • Check out the development status of each item. For now it is a two state status: undone/done. We will migrate in the coming months to a three-states one: draft/ready-to-implement/done, so that you know how ready we are to implement the feature.
  • Get links to source code, user & dev documentation pages, blog posts and videos of items that are already done, so that you can use it as a tool for staying up-to-date with how the platform evolves. On this site, the information will always remain at a high level so that it is easy to get “reloaded” with the newest Nuxeo Platform knowledge whenever you need. This is complementary to the release notes site where you find the exhaustive version of all the work that has been done on a release.
  • See mockups of upcoming roadmap items.

Generation of the Nuxeo roadmap page is dynamic (see last paragraph of this post), which means it really reflects the current state of our roadmap. Every year at Nuxeo we set the main direction for the next LTS and do our best to achieve our goals. The order and path may change depending on events. Sometime we have good surprises or new ideas, and problems also happen. That’s the life of a product!

Hence this Nuxeo roadmap is not a contract, but a great opportunity for you to monitor where we are headed. Use it as an opportunity to give us your feedback.

In the future we will improve it with notifications, comments, better status of roadmap items and easy access to module specifications.

Now what about what’s in the roadmap itself? Other than working on the user experience of existing products like Nuxeo Drive and Studio, our focus is on:

  • Scalability, with integration of Elastic Search in the next fast track and a bit later a NoSQL implementation of the repository.
  • The cloud, with the opening of nuxeo.io in Q2 (stay tuned for more information on this topic). We will also work on integrating with Codenvy, the online development platform, to provide you with a 100% cloud experience from design to implementation, going through development.
  • Mobility, with an iOS app for iPads and iPhone later on, and the release of the Android SDK.
  • JavaScript, continuing to improve integration with the JavaScript world, especially with the AngularJS framework.

Finally, you may be interested in understanding how this tool was made. We use a dedicated JIRA project called NXROADMAP where I maintain elements of the roadmap. From the roadmap site, you can access the corresponding JIRA ticket by clicking on the small corresponding icon on the top-right corner.Image may be NSFW.
Clik here to view.
linkToRoadmapItem

We used Bootstrap and a small JIRA API JavaScript client found on GitHub that wraps the JIRA REST API. Our interest to stay with JIRA is because in JIRA we link the roadmap items to real implementation tickets, which makes it easy to get the status of a given roadmap item. Source code is available on GitHub.

The post The Nuxeo Roadmap on www.nuxeo.com appeared first on Nuxeo Blogs.

How to Set Up Notifications When Video Conversions Are Finished

Image may be NSFW.
Clik here to view.
How to Setup Notifications when Video Conversions are Done?

Last week I blogged about video conversion profiles in the Nuxeo Platform. I explained how to configure them, add new, or disable existing ones. Today I will show you how to setup notifications when those video conversions are done. It’s actually pretty simple.

There is a videoConversionsDone event launched each time a video conversion is done (who would have known?). Unfortunately, it’s not available in Nuxeo Studio by default. But we can make it available thanks to the Nuxeo Studio registries.

To do that go to Settings and Versioning > Registries > Core Events. You should see a text editor. It accepts a JSON string that represents the event we want to add. Here it is:

{
  events: {
    videoConversionsDone: "Video Conversion Done"
  }
}

Now click on save and create a new Event Handler. At the end of the Events list, you should see Video Conversion Done. Select it and create the associated operation chain.

This operation takes the Video document as input. The notification event is different than the usual one from the CoreSession (documentModified, documentCreated etc…). So we cannot use the CurrentUser object. It’s null.

Instead, we have the Event object in the operation context. But the sad news is this user is System. This is because the video conversions are done inside a Worker by the System user. So if we want to send an email to the document creator or last modifier, we need to proceed differently.

In the Nuxeo Platform all the documents having the dublincore schema (all the default ones) have a Last Contributor property (dc:lastContributor). This is exactly what we need. This way we cover the creation and modification of the document. In Nuxeo Studio you can retrieve the email of the last contributor of a document with the following MVEL expression:

@{Fn.getEmail(Document["dc:lastContributor"])}

My final operation chain looks like this:

Fetch > Context Document(s)
Notification > Send E-Mail
  from: admin@mydomain.com
  message: template:videoConversionDone
  subject: @{Document["dc:title"]} Video Conversion Done
  to: @{Fn.getEmail(Document["dc:lastContributor"])}
  HTML: X

The template:videoConversionDone property refers to an email template I created in the appropriate Nuxeo Studio section. Here’s the template content:

Hello,

The video conversions for the document <a href="${docUrl}">${Document['dc:title']}</a> are done.
How AWESOME is that?

Cheers,
The Nuxeo Platform

I talked about this with Thibaud and he went even further with this mail template:

<p>Hi,</p>
<p></p>
<p>Conversions for <a href='${docUrl}'>${Document['dc:title']}</a> are ready:</p>
<p><ul><#list transcodedItems as oneItem>
<li>${oneItem.name}</li>
</#list></ul></p>
<p></p>
<p>The Video Conversion Service</p>

This email lists all the conversions currently available on the document. He can do this because he has added the transcodedItems variable in the operation context. He did this by adding the Set Context Variable operation just before the Send E-Mail:

Execution Context > Set Context Variable
name: transcodedItems
value: @{Document['vid:transcodedVideos']}

If you want to go further, you can try adding thumbnails of the video in the email :)

The post How to Set Up Notifications When Video Conversions Are Finished appeared first on Nuxeo Blogs.

Hot Folder Uploader

What is a hot folder? Well. You sure know what a folder is: A container, a directory on your drive. Now, what does it mean when a folder is hot?

Let’s start with what it does not mean:

  • The folder is not at a “high degree of heat, or high temperature”
  • It is not particularly sexy, nor attractive(1)

No. A hot folder actually is a folder whose content is permanently watched: When it is empty, nothing happens. When it contains at least one file, something happens.

In this article, that “something” is an upload of the files in the hot folder to a Nuxeo server. All is based on a shell script using bash(2). You can find the final script here, while in this article we are going to talk about the main principles. Here they are:

  • Having a script (an executable .sh file) which:
    • Loops on every file in the folder
    • Sends each one to Nuxeo, using curl
  • Adding it to your cron system. This is what makes the folder hot actually.

Let’s start with the script.

It needs the following information:

  • The Nuxeo server URL,
  • The destination container in this server (where the documents will be created), and
  • The credentials to access the server.

You will find them at the top of the script. Just make sure the credentials you are using allow creating documents in the destination container:

SERVER_BASE_URL=http://localhost:8080/nuxeo
USER_LOGIN=Administrator
USER_PWD=Administrator
# This folder, or workspace, or container *must*:
# - Exists
# - Have ACL which allows USER_LOGIN to create document
NUXEO_DESTINATION_URL=$SERVER_BASE_URL/api/v1/path/default-domain/workspaces/hot-folder-import

Next, we need to create the correct type of document in Nuxeo. We don’t want to always create File documents if, for example, we are sending images or videos: We would not have preview, Storyboard, IPTC extraction, etc… To achieve this requirement, the script gets the mime-type of the file, and decides what kind of Nuxeo document to create. In my first tests it did not always work as I wanted. I found that .jpg, .png, .doc, .mp4, .avi, … files were correctly handled, but I had some raw pictures which were not recognized as “image/*” mime type. So, I added some more testing:

. . .
nuxeo_doc_type="File"
mime_type=`file --mime-type -b "$file"`
case "$mime_type" in
  image/*) nuxeo_doc_type="Picture";;
  video/*) nuxeo_doc_type="Video";;
  *)
    case $file in
      *.mov) nuxeo_doc_type="Video";;
      *.ORF) nuxeo_doc_type="Picture";;
      *.xmp) nuxeo_doc_type="Picture";;
      *) nuxeo_doc_type="File";;
    esac
esac
. . .

Something quite interesting is that you could also ask Nuxeo to create your own custom document type, the one that you defined in Studio. Look at the “Room for enhancement” part of the README on GitHub; there already are some ideas.

Creating the document, with its file, in Nuxeo is pretty easy with curl. Well, I found it very easy because I found YABFL(3) here. So, in a question of minutes, the script was ready – just the time to make typos and mistakes in passing the correct dynamic parameters to curl.

Here is the send_to_nuxeo function (I removed test/log here, so it’s easier to read the main parts):

function send_to_nuxeo {
file_full_path=$1
doc_type=$2
filename="${file_full_path##*/}"
# Just cleanup spaces here
filename_clean=${filename// /_}

# Send the binary to nuxeo, using the file name as batch id
curl -H "X-Batch-Id: $filename_clean" -H "X-File-Idx:0" -H "X-File-Name:$filename" -F file=@"$file_full_path" -u "${USER_LOGIN}":"${USER_PWD}" "${SERVER_BASE_URL}/api/v1/automation/batch/upload"

# Create the document, asking nuxeo to use the file in this batch-id
curl -X POST -H "Content-Type: application/json" -u "${USER_LOGIN}":"${USER_PWD}" -d "{ \"entity-type\": \"document\", \"name\":\"${filename_clean}\", \"type\": \"${doc_type}\", \"properties\" : { \"dc:title\":\"${filename}\",\"file:content\": {\"upload-batch\":\"${filename_clean}\",\"upload-fileId\":\"0\"}}}" "${NUXEO_DESTINATION_URL}"

# Move of delete the file
if [ -n "$COPY_DEST_FOLDER" ]; then
mv "$filename" "$COPY_DEST_FOLDER/$filename"
else
rm "$filename"
fi
}

You can quick-test this script. Just make sure the user running the script has enough rights on the hot folder, and possibly on the hot folder backup folder if you used it.

We now find ourselves with this wonderful script. But something is missing: So far, we don’t have a hot folder, do we? We ran this script manually. Our folder is just a folder. A regular, basic, nothing-special folder. We want to make it hot! We want to make it useful! We need to make the system run the script on a regular basis. One way to do it is to add the script (and its parameters) to our cron system. For example, to run the script every minute, you can use the crontab command. So you crontab -e, which opens the configuration file in vi, where you can add this line:

* * * * * "/path/to/script" "/path/to/hot-folder"

(Possibly, you would also add the 2nd parameter, to move the files instead of deleting them)

Isn’t this folder pretty hot?

(1) If you truly find yourself thinking a folder on your screen is attractive, then please, stop reading right now. Drop your pizza, take a shower, open the window, then open the door and take a walk outside. It’s the doctor speaking.
(2) So it is mainly for Linux servers. Or Mac OS when doing quick tests. Sorry, not Windows. But I’ll be very happy to add your script for Windows to this GitHub repository.
(3) Yet Another Blog From Laurent

The post Hot Folder Uploader appeared first on Nuxeo Blogs.

Monitoring Nuxeo Docker Container Logs with Logstash, Elasticsearch and Kibana

Image may be NSFW.
Clik here to view.
Logstash

A while ago I wrote a blog post about CoreOS and monitoring the Nuxeo Platform. It covered gathering the metrics of a Nuxeo Platform Server, the associated PostgreSQL database and the host system. The particularity of this setup was that the host was a Docker container running on CoreOS.

Today I will cover another aspect of monitoring – the log files. The goal is to store all the log entries from Nuxeo, Apache and PostgreSQL inside Elasticsearch. Then, they are easy to browse with Kibana. To forward the logs to Elasticsearch, I will use LogStash.

The first step was to setup Docker containers with Logstash, Elasticsearch and Kibana. It’s easy as a lot of images already exist in the Docker index.

Elasticsearch

Elasticsearch is an open source distributed search engine. This is where all my log entries will be stored. And it actually has its own official image. So we can use it directly:

docker run -name elasticsearch -h elasticsearch -d -P dockerfile/elasticsearch

This command pulls the image directly from the public Docker index and runs it as daemon. As we have not declared any port mapping, you need to inspect the running container. The docker ps is enough for that. You should see something like:

CONTAINER ID        IMAGE                             COMMAND                CREATED             STATUS              PORTS                                              NAMES
92ea2c4fdb69        dockerfile/elasticsearch:latest   /opt/elasticsearch/b   6 seconds ago       Up 5 seconds        0.0.0.0:49153->9200/tcp, 0.0.0.0:49154->9300/tcp   elasticSearch

This means that on my docker host, the Elasticsearch server 9200 port is accessible from the port 49153 and 9300 from 49154.

Kibana

Now about Kibana. It’s an AngularJS application backed by the Elasticsearch team. This app lets you query and display results from an Elasticsearch instance. It’s particularly well suited for log aggregators like Logstash or Flume, among others.

I found a cool Dockerfile and its related blog post. I updated it a little to have the latest Kibana version.

Basically, it installs nginx, the latest Kibana release and sets them up. Here’s the Dockerfile:

# Kibana image started from arcus-io/docker-kibana
FROM base
MAINTAINER ldoguin
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y wget nginx-full unzip
RUN (cd /tmp && wget --no-check-certificate http://download.elasticsearch.org/kibana/kibana/kibana-latest.zip -O pkg.zip && unzip pkg.zip && cd kibana-* && cp -rf ./* /usr/share/nginx/www/)
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
ADD run.sh /usr/local/bin/run
RUN chmod +x /usr/local/bin/run
RUN rm -rf /tmp/*

EXPOSE 80
CMD ["/usr/local/bin/run"]

This is the run script. It gathers environment variables called ES_HOST and ES_PORT. They should, as you probably guessed, already be the Elasticsearch container hostname and the mapped port 9200 (49153 for my current setup). They are then used by the Kibana configuration file to build the address Kibana uses to query Elasticsearch. The queries are run through your browser, so you can’t use the private Docker port and address you usually retrieve by linking containers.

#!/bin/bash
sed -i "s/elasticsearch: \"http:\/\/\"+window.location.hostname+\":9200\",/elasticsearch: \"http:\/\/$ES_PORT_9200_TCP_ADDR:$ES_PORT_9200_TCP_PORT\",/g"  /usr/share/nginx/www/config.js
nginx -c /etc/nginx/nginx.conf

This is the command I use to run the Kibana container:

docker run -d -P -h kibana -name kibana -e ES_HOST=docker -e ES_PORT=49430 nuxeo/kibana

Environment variables are given to the container using the -e option. Now you should have a running Kibana.

Logstash

Logstash is also backed by the Elasticsearch team.

Logstash helps you take logs and other event data from your systems and store them in a central place.

Again, I start from the arcus-io Dockerfile to get a slightly different version with the OpenJDK and the latest Logstash version.

# Logstash image started from https://github.com/arcus-io/docker-logstash
FROM ubuntu:quantal
MAINTAINER ldoguin "ldoguin@nuxeo.com"

RUN echo "deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse" > /etc/apt/sources.list
RUN apt-get update

# Small trick to Install fuse because of container permission issue.
RUN apt-get -y install fuse || true
RUN rm -rf /var/lib/dpkg/info/fuse.postinst
RUN apt-get -y install fuse

RUN apt-get install -y wget openjdk-7-jdk
RUN apt-get install -y curl
RUN curl -O https://download.elasticsearch.org/logstash/logstash/logstash-1.4.0.beta2.tar.gz
RUN tar zxvf logstash-1.4.0.beta2.tar.gz
RUN mv logstash-1.4.0.beta2 /opt/logstash

ADD run.sh /usr/local/bin/run
ADD logstash.conf /opt/logstash/logstash.conf

EXPOSE 514
EXPOSE 9200
EXPOSE 9292
EXPOSE 9300
CMD ["/usr/local/bin/run"]

And this is the associated run.sh file:

#!/bin/bash
ES_HOST=${ES_HOST:-127.0.0.1}
ES_PORT=${ES_PORT:-9300}

sed -i  "s/elasticsearch { host => docker }/elasticsearch { host => \"$ES_HOST\" port => $ES_PORT }/g" /opt/logstash/logstash.conf

/opt/logstash/bin/logstash -f /opt/logstash/logstash.conf  --verbose

I setup my own logstash configuration to handle log entries coming from PostgreSQL, Nuxeo Platform and Apache.

Here we replace the Elasticsearch settings by the one given by the environment variable. Then I can run it like this:

docker run -d -P -volumes-from nuxeoserver -e ES_PORT=49431 -e ES_HOST=docker -name logstash nuxeo/logstash

The -volumes-from option is here to tell our container to use the volumes defined in the nuxeoserver container. It means I already have a nuxeoserver container running with some defined volumes. These volumes are the folders containing the logs I am interested in.

This is the command I used to run my nuxeoserver container:

docker run -h nuxeoserver -P -d -volumes-from logsData -name nuxeoserver nuxeo/nuxeo

The Nuxeo container references another volume called logsData. Here’s how I run it:

docker run -v /var/log/apache2 -v /var/log/postgresql/ -v /var/log/nuxeo/ -name logsData busybox true

This is a data-only container. What it does is simply run a container with predefined volumes and exits immediately. But you can still use it thanks to the -volumes-from option. It makes it easy to share volumes between containers or to export data stored in the data-only container. In a production environment for instance, I would have probably added the Nuxeo and PostgreSQL data directories.

If you want to learn more about the data-only container I suggest you read this great post from Michael Crosby.

Anyway, now everything is set up. If you go to Kibana, you should see the default welcome page. There is a link to their default Logstash dashboard. Click on it and you’ll see your log event piling up.

Image may be NSFW.
Clik here to view.
Kibana

The post Monitoring Nuxeo Docker Container Logs with Logstash, Elasticsearch and Kibana appeared first on Nuxeo Blogs.

[Nuxeo Tech Report] News from the Developer Front #13

It’s been a while since I published a tech report. We made some changes in the way we handled them internally, adjusting the process a bit. But here it is again! It’s a little shorter than usual, but hopefully we’ll publish more than once a month.

What’s on tap:

 

 

Core Session Management

Florent is cleaning up CoreSession management: NXP-13148. Goal is to make sure that sessions are always removed as soon as they are no more used, as currently, there are some situations where the linked vcs connection is already freed, and the core session is still alive, which means that we keep an object that would never have any chance to connect and be used again. With Stéphane’s work on database connection, it is the beginning of a virtuous cycle on freeing all objects that are useless at all the levels: datasources, vcs pool, core sessions, and then Seam beans. This task will open the way to a less stateful Seam/JSF web app, increasing its scalability and simplifying programmation patterns.

 

Elasticsearch Integration

After completing some tests and benchmarking on Elasticsearch, we have started the Java integration. The umbrella task is NXP-14007. We are just beginning to have a way to start Elasticsearch with a Nuxeo Server and index/query Documents.

Not surprisingly, we are finding the same constraints we had previously with Compass integration (Nuxeo 5.3 and before), but the good news is that Nuxeo now offers more infrastructure:

  • Transactional test infrastructure,
  • WorkManager,
  • Improved post commits, and
  • JSON Marshaling.

In the current state, we have a service with a default configuration:

  • Support for indexing and re-indexing
  • Support for query (including security filtering)
    • In native Query DSL
    • In NXQL
    • With PageProviders

Simplified ACLs

Florent created NXP-14045 for Simplified ACLs. It mostly means removing the ability to have negative permissions (deny), beside the deny everything (= block inheritance) that is still accepted. This simplifies the computation that is executed in the hierarchy to know the permissions of a user on a document. It thus allows some interesting optimisations,  and is anyway likely to be needed by the Elasticsearch indexing.

WAR Packaging

We recently had several customers wanting to deploy on JBoss or WebSphere. We know that making Nuxeo deploy in dynamic mode on several application servers needs a lot of work. However, doing this using a static WAR:

  • Should be much simpler, and
  • Should be enough for most use cases.

This also mean that we will have to completely embedding DataSource management in Nuxeo, and  Isolating the nuxeo.war class loader to avoid lib conflicts.

NXP-14087 was created for this purpose. It is not a big task and It will be added to the roadmap as it is identified as  an important

REST API

We have gathered all the feedback we got since the release of Nuxeo Platform 5.8 and the beta version of the Nuxeo REST API. Goal is to have a definitively stable and great api for 6.0. Do not hesitate to give your feedback too!

Improve HTTP Return Codes

In some cases we don’t return the expected/valid http return code.

  • Bad return code in DELETE NXP-14076
  • CREATE returns 200 instead of 201

Problem with JSON typing

It looks like the default marshaling is not correct: in the JSON stream “everything is string”

=> https://jira.nuxeo.com/browse/NXP-12614

Content Types

Currently in Automation, content-type is not handled by an HTTP header, but inside the JSON stream. This design comes with several flaws:

  • The client code needs to do something like jsonResult.value
  • When posting back the data to the server, the client needs to re-encapsulate in a JSON structure like
     { "entity-type": "IoApplication", "value": { ...real data here ... } } ) 
  • It makes HTTP Content-Type meaningless for us
    • In some cases we enforce using a Content-Type like application/json+nxautomation: this is meaningless and error prone
    • We could use Content-Type header to select adapters: this would avoid having '/@bo/' urls

Hopefully, we should be able to make the change while keeping compatibility: both models should be able to work in parallel so that we don’t have to update all Automation Client libraries.

Business Adapters

Business adapters are not that easy to use:

  • Same issue on the PUT adapter as the id problem we had on the Document end point,
  • Add support for DELETE on adapter,
  • Automatic name generation via Adapter.

We need to extend the Business adapters to entities that are not DocumentModel: typically the User endpoint would benefit from this feature.

Extend Bindings

We have been talking about adding new bindings that could make the developer’s life easier:

  • Call an operation using a GET request
    • Useful to retrieve a Blob and display it as an image
    • This creates potential security issues
  • Add QueryString parameters in the REST API
    • ex: create a version when updating a Document

The post [Nuxeo Tech Report] News from the Developer Front #13 appeared first on Nuxeo Blogs.

CoreOS and Nuxeo: How We Built nuxeo.io

If you follow the Nuxeo blogs, you may have seen that we have been working with Docker for a few months now. Not because it’s very trendy, but because we will be using it in the infrastructure of nuxeo.io. In this post I will explain how we see our global infrastructure.

A Platform Designed for Failure

One of the things we learned when reading about building a cloud platform is that the system must be resilient to failure. This means that a host may be down, a process may halt, etc., but your platform must live with that. If a node of your cluster goes down, the service shouldn’t be altered, and the system must react automatically to re-balance the missing services on other nodes – very fast.

This is where Docker comes in. Since the kernel is shared by all the containers, the startup time of a service is very quick – no need to provision a virtual machine for instance. To start a new Nuxeo container, it only takes about 30 seconds.

Cluster Management

When you need to start a lot of containers, you have to find a way to manage them. This means knowing if they are started, where they are located, etc… In order to do that, we found etcd, a distributed registry across a cluster. When we set a key in that registry from one host, it is then accessible from all other hosts in the cluster. Moreover, we can watch for key modifications and setup a TTL for a key. This last feature allows us to very quickly setup a heartbeat mechanism.

As etcd is part of CoreOS, we look at that distribution which is a tiny distribution that embeds Docker, etcd and systemd. Systemd allows us to start Docker containers, but we don’t use it directly. We use fleet which can be seen as a “systemd over a cluster” – it is also bundled with CoreOS.

With all that stuff, we have a running cluster that is synchronized, and on which we can run services. Each time we start a service, we register it in etcd with its attributes (ip, port). For instance we have a docker registry service that holds our private container images.

Data Free Runtime Containers

Remember now that we want to be able to deal with failures. If a Nuxeo server goes down, or is frozen or whatever, we destroy it and restart it with fleet. That means we loose all data may be held in our container. We could restart the instance, analyze things and get back the data, but it’s too long and requires an administrator operation.

In our cluster configuration, every Docker image in the stop status is destroyed. We treat our container as an execution part of the platform – it can run everywhere in the cluster. This means that the database and the binary manager must be exernalized, and the logs as well.

Dynamic Virtual Hosting and Load Balancing

The other part of the cluster is the public facing part. In order to achieve that we need to route and balance the requests for a given host to the proper container serving the request.

A dynamic proxy doesn’t route requests based on a configuration file, but on a route database that can be altered without having to restart the process.

In our cluster we have such a database – it is etcd. Each domain we want to serve will have its own key, and each key will reference an environment id (i.e. a running Nuxeo instance).

There are already some dynamic proxy implementations, but no one fit our needs.

  • Hipache stores its data in Redis,
  • Strowger uses some Flynn primitives that we don’t want to depend on,
  • Active-proxy: This was just a POC and hasn’t evolved in a long time (meaning several months, which is very long in the Docker ecosystem ;-) ), and
  • Boxcars: Based on a configuration file and has some use cases we don’t need.

As none of them met our needs, we decided to develop our own reverse proxy called Gogeta, reusing some basic ideas from several tools we looked at:

  • Written in Go: generates a native executable and has some basic primitives to run a proxy server,
  • Gets and watches its configuration from etcd, and
  • Keep it small and simple (KISS)

Big infrastructure picture

In the following picture we can follow how a request is issued to a container:

  • The user enters http://mydomain.nuxeo.io/.
  • It ends on the front load balancer that randomly sends the request to one of the coreOS hosts on the Gogeta endpoint.
  • Gogeta reads etcd in the /domains keys to know that it must proxy on the NXIO-0001 container.
  • Gogeta gets the properties of NXIO-0001 in etcd, checks that the status is okay and proxies the request.

On the bottom, fleet helps us to start new containers in the cluster.

Image may be NSFW.
Clik here to view.
Nuxeo.io infrastructure

Conclusion

Docker is a good piece of software to build a fault tolerant infrastructure. CoreOS provides us with a cool integration of it, providing us the missing tools to manage the cluster.

nuxeo.io will be soon open-sourced (some parts of it are already done), so you can play with it and give us some feedback. When we think it is ready for testing, then we will announce it. Stay tuned !

The post CoreOS and Nuxeo: How We Built nuxeo.io appeared first on Nuxeo Blogs.

How to Add a Custom Export Asset Button to a Document

Downloading a custom export of an asset in a different form than its original one is a common request from our users. Using a bit of Nuxeo Studio and the converter extension point, you’ll see that it’s pretty easy to achieve.

As an example let’s say we want to watermark a picture asset with some text. When you add a new button to Nuxeo, you have to define when it will be displayed and what it will do.

First let’s see about the when. Using Nuxeo Studio, you need to create a new User Action through the Automation > User Actions menu. Here you can select a category. It’s where your button will be displayed. If you select “DAM Asset view actions” it will display the button on the DAM tab along with the actions available on the single asset view on the right.

Image may be NSFW.
Clik here to view.
New User Action

Now as the goal is to watermark pictures, we don’t want to display the button when something other than a picture is selected. To do that you simply select the Picture type in “Action Enablement > Current document has one of the types” menu.
Image may be NSFW.
Clik here to view.
Action Filter

Then, if you hit the save button, Studio will warn you that there is no automation chain associated to the current button. So click on create, pick a name and Studio will automatically send you to the new automation chain screen. Here we can define what we want to do with our Picture asset.

What we’ll need now is an operation that can actually do the watermarking. This is not available by default, but we can add it easily with Nuxeo IDE. Use the new operation wizard to start a brand new operation. Let’s call it GenericConverter. It will take as parameter a converter name and a map of parameters. Take a look at the code:

package org.nuxeo.presales.toolkit.images;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.automation.core.Constants;
import org.nuxeo.ecm.automation.core.annotations.Context;
import org.nuxeo.ecm.automation.core.annotations.Operation;
import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
import org.nuxeo.ecm.automation.core.annotations.Param;
import org.nuxeo.ecm.automation.core.collectors.BlobCollector;
import org.nuxeo.ecm.automation.core.util.Properties;
import org.nuxeo.ecm.core.api.Blob;
import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
import org.nuxeo.ecm.core.api.blobholder.SimpleBlobHolder;
import org.nuxeo.ecm.core.convert.api.ConversionService;
import org.nuxeo.runtime.api.Framework;

/**
* @author fvadon and aescaffre
*/
@Operation(id = GenericConverter.ID, category = Constants.CAT_CONVERSION, label = "GenericConverter", description = "")
public class GenericConverter {

    public static final Log log = LogFactory.getLog(GenericConverter.class);

    @Param(name = "converterName")
    protected String converterName;

    @Param(name = "parameters", required = false)
    protected Properties parameters;

    public static final String ID = "GenericConverter";

    @OperationMethod(collector = BlobCollector.class)
    public Blob run(Blob input) {
        try {
            ConversionService conversionService = Framework.getService(ConversionService.class);
            BlobHolder source = new SimpleBlobHolder(input);
            Map<String, Serializable> serializableParameters = new HashMap<String, Serializable>();
            if (parameters !=null) {
                Set<String> parameterNames = parameters.keySet();
                for (String parameterName : parameterNames) {
                    serializableParameters.put(parameterName, (Serializable) parameters.get(parameterName));
                }
            }
            log.debug("Converter Being called:"+converterName);
            BlobHolder result = conversionService.convert(converterName, source, serializableParameters);
            return result.getBlob();
        } catch (Exception e) {
            log.error("Error during conversion",e);
        }
        return null;
    }

}

As this operation can take any converter as parameter, we can create a new one that will do the watermarking. To achieve this, we can simply add some text as overlay on the existing image.

Adding a converter is easy. Most of them are usually based on a commandLine executor. So what we’ve done is create a generic converter called GenericImageMagickConverter that takes as a parameter the name of the commandLine executor to use. Here’s the code to create the generic converter:

package org.nuxeo.presales.toolkit.images;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
import org.nuxeo.ecm.core.convert.api.ConversionException;
import org.nuxeo.ecm.platform.convert.plugins.PDF2ImageConverter;

public class GenericImageMagickConverter extends PDF2ImageConverter {
	public static final Log log = LogFactory.getLog(GenericImageMagickConverter.class);
	@Override
	protected Map<String, String> getCmdStringParameters(BlobHolder blobHolder,
			Map<String, Serializable> parameters) throws ConversionException {
		Map<String, String> cmdStringParameters= super.getCmdStringParameters(blobHolder, parameters);
		Map<String, String> stringParameters = new HashMap<String, String>();
		Set<String> parameterNames = parameters.keySet();
		for (String parameterName : parameterNames) {
			//targetFilePath is computed by the method of the superType
			if (!parameterName.equals("targetFilePath"))
			stringParameters.put(parameterName, (String) parameters.get(parameterName));
		}
		cmdStringParameters.putAll(stringParameters);
		return cmdStringParameters;
	}

}

Most of the time when you add Java code in a Nuxeo bundle, it’s tied to an extension point. Here, our generic converter is of course linked to the converter extension point:

<component name="org.nuxeo.presales.toolkit.images.conversions">
    <extension target="org.nuxeo.ecm.core.convert.service.ConversionServiceImpl"
      point="converter">
        <converter name="overlaying" class="org.nuxeo.presales.toolkit.images.GenericImageMagickConverter">
          <parameters>
            <parameter name="CommandLineName">imageOverlay</parameter>
          </parameters>
        </converter>
    </extension>
</component>

And the imageOverlay commandLine executor defined in the converter has to be defined in the right extension point too:

    <extension target="org.nuxeo.ecm.platform.commandline.executor.service.CommandLineExecutorComponent"
      point="command">
      <command name="imageOverlay" enabled="true">
        <commandLine>convert</commandLine>
          <parameterString>#{sourceFilePath} -gravity #{gravity} -fill #{textColor} -stroke '#070536' -strokewidth 2
             -pointsize #{textSize} -annotate #{textRotation}x#{textRotation}+#{xOffset}+#{yOffset}
              #{textValue} "#{targetFilePath}"</parameterString>
          <installationDirective>You need to install ImageMagick.</installationDirective>
      </command>
    </extension>

As you can see it’s an ImageMagick command that will overlay some text on the given image. Okay, maybe you can’t see it just by looking at the command line :) We’re not all ImageMagick gurus…

Now that we have a converter, we can deploy this code using the Nuxeo IDE. We can also send the new operation definition to Nuxeo Studio using the export button available on the IDE. If you don’t know how to do this I strongly recommend you read the quick start dev guide.

Once this part is done we can go back to our operation. What we’re going to do first is set a context variable that will hold the text we want to overlay. Then we get the main file of the document and assign to the filename variable the filename of the main file. We’re going to use it in the operation parameter.

The next step is to resize the current image to 800×600. Controlling the size of the image is important as our overlay operation will have predefined parameters like the size of the text and its position. We could probably do something proportional to the size of the image being converted but let’s keep things simple.

The next step is to call the actual overlay operation. You can see in the given parameters that we are using the context variables we previously defined. If Bill created the image and downloads the export April 11, 2014, the resulting image will have a text overlay like Copyright: Bill-2014.

The final step is to use the Download file operation that will actually send the converted file back to the user.

Fetch > Context Document(s)
Execution Context > Set Context Variable
    name:
        textValue
    value:
        Copyright: @{Document["dc:creator"]}-@{CurrentDate.format("yyyy")}
Files > Get Document File
    xpath:
        file:content
Execution Context > Set Context Variable
    name:
        fileName
    value:
        @{This.filename}
Conversion > Resize a picture
    maxHeight:
        600
    maxWidth:
        800
Conversion > GenericConverter
    converterName:
        overlaying
    parameters: 
        targetFilePath=@{fileName}
        textColor=Yellow
        textValue=@{textValue}
        gravity=SouthWest
        textRotation=0
        xOffset=0
        yOffset=0
        textSize=42
User Interface > Download file

Now you are all set to try this watermarking operation. Keep in mind that using these converters you can add pretty much any kind of export you want. And if you want to make them more configurable, you can always make the parameters of the operation configurable through a workflow (which might be the subject of another blog post in the near future).

The post How to Add a Custom Export Asset Button to a Document appeared first on Nuxeo Blogs.


Nuxeo Platform 5.9.3 is Available: Elasticsearch, Collections and More!

Image may be NSFW.
Clik here to view.
Nuxeo Platform 5.9.3
We just released our latest Fast Track version – Nuxeo Platform 5.9.3. Note that Fast Track versions are only supported until the next FT (Check out this blog post about our release life cycle).

Take a look at the 5.9.3 release notes for the whole story.
Image may be NSFW.
Clik here to view.
nl-elasticsearch

The first major feature of this release is the integration of Elasticsearch. It brings greater scalability to the Nuxeo Platform. We use it to index all the documents in your instance. When you install this module, all the common page providers will query Elasticsearch instead of your RDBMS.

Another great addition that comes with 5.9.3 is the Collections type. A Collection is a folder-like document in which you classify existing content. Documents are not actually copied or moved into the collection, it only holds a link to the document in its original location.

If you follow the blog, you also know that we released an open-source implementation of the Box API that runs on top of a Nuxeo repository. The use cases we see for the Nuxeo Box API:

  • Allow developers to run “their own local Box server” using the Nuxeo Platform. This enables them to run a Box server locally, in a continuous integration chain, great for testing Box-based applications.
  • Serve customers with on premises requirements (or different cloud infrastructures).

There are a lot of other new features that you can read about in the release notes and even try by downloading Nuxeo Platform 5.9.3 from our website.

Now, we are on to Fast Track 5.9.4 which should be released in June. Check out our roadmap for more information.

The post Nuxeo Platform 5.9.3 is Available: Elasticsearch, Collections and More! appeared first on Nuxeo Blogs.

A Spreadsheet Editor for Lists of Documents in the Nuxeo Platform

The Nuxeo roadmap put a lot of emphasis on working with large collections of assets or documents, leading to the new collections module, as well as some upcoming updates around the user experience when selecting values in a content view.

One particular item of the roadmap focuses on the ability to edit data in your repository as if you were in a spreadsheet-like grid. Indeed, spreadsheet copy-paste by dragging the cell’s value is something very intuitive and very productive for handling bulk-editing of thousands of documents. We want to somehow emulate this behavior. One of the challenges is that when you handle documents in a repository, you have to respect some constraints:

  • Some metadata is mandatory,
  • Some have constrained values among a controlled list, that store the id value while it displays the label,
  • You may even have more complex validation logic,
  • Sometimes some information is read-only, you don’t want to let the user modify it,
  • This is not a constraint, but a must: you want to be able to use Nuxeo Studio for configuring the spreadsheet instance, mapping that configuration to the notion of result layout.

You need to make sure your user interface will be able to enforce all those constraints. There are two ways to implement a spreadsheet editor:

  1.  Produce a clean Excel/Open Office /CSV export of the data, let the user do their modification in the desktop application, then re-import the new table updating the related documents in the repository.
  2. Have a built-in table-like solution, that will emulate the user interface of Excel, to edit the data.

I have a reported implementation of method 1 by one of our customers. They used the XML Excel format for producing a file that has some locked cells, controlled lists, etc … The production of the file is based on rendering logic that injects values in the initial template. They reported having issues making sure the Excel file was okay, with the correct protection of cells, etc … But, this is still doable, with some limitations on the kind of controls that can be presented to the user.

Another approach still based on exporting an Excel file could be to use advanced templates based on JXLS library. I am pretty sure we could produce an interesting template, here also with some limitations to the kind of widgets available for editing the data.

For method 2, I found a library that could be the basis of our future implementation of https://jira.nuxeo.com/browse/NXROADMAP-159: handsontable.js. This awesome library implements the spreadsheet user experience in a JavaScript grid and provides all the plugability you would expect from such a component.

I have played with it a little bit using the nuxeo.js JavaScript client - the result is on github (pardon my JavaScript ;)) and I did a short video to share the result:

In short, what the library allows you to do is:

  • Define the datasource that you map to a Nuxeo query (preferably using the PageProvider operation, that allows you to control the max result). It is possible to have advanced mappings (subfields to column).
  • Define the columns that should be displayed.
  • Define their type, the renderer to use for presenting the value, as well as the editor for editing. You can write your own renderers and editors. For instance, I have adapted and integrated a select2 editor (that was implemented by someone else and found on github). This means we can theoretically map all of our widget library.
  • Define which columns are editable or not.
  • Define formatters, so as to control the police, the size and the colors of the cell depending on some business rules, as well as if it should be displayed as numbers, etc…
  • Benefit from the undo/redo user experience.
  • Provide built-in search filtering capabilities.
  • Register to any of the events that happen on the table, to have a tight link of your backed model to what the user does on the table.

What we should do to integrate it nicely into the Nuxeo Platform:

  • Integrate the table to content views. It could be either another result layout (like the lightbox one is going to be) or just a new button on the content views template that displays it in a pop up.
  • Plug the data of the Handsontable to the state of the content view: user filters data on the content view, then extracts the result into the JavaScript grid to edit it.
  • Implement a homogeneous set of editors and renderers mapped to the main widgets of our layout library.
  • Plug the Handsontable instantiation definition to the layout service so as to be able to configure it from Studio.
  • Implement pagination logic for fetching larger sets of data.
  • Implement a robust bulk-save of the rows updates (currently, I call the REST API row by row, which actually happens to give a very good results already).

As you can see, this is a full time job, but this first integration attempt is already promising! If you are curious for some more “hands-on” details, here are some of the interesting parts. I use the Nuxeo JavaScript client, so I need to instantiate it:

<br />var connectInfo = {<br />baseURL: "http://demo.nuxeo.com/nuxeo",<br />username: "Administrator",<br />password: "Administrator",<br />timeout: 300000,<br />schemas: "dublincore"<br />};<br />var client = new nuxeo.Client(connectInfo);<br />

I start by fetching the data (the whole code is wrapped in a function with queryString param, so as to easily instantiate the table with query based content. Note the use of Document.PageProvider, as it is paginated, versus Document.Query, which would not scale for a large repository:

&lt;<br />client.operation('Document.PageProvider') .params({ query: queryString, maxResults:"500", pageSize:"500" }) .execute (…)<br /><br />

Then in the call back function of the execute method, I instantiate the Handsontable:

<br />$("#example2").handsontable(handsonOptions); // #example2 is a div in the page, handsonOptions is an array with the options.<br />

The main options I use are:

data: the data to be injected in the table, it is the direct data result of the Document.PageProvider operation

columns: an array of the definition of the columns type. Ex:

<br />columns: [ {<br />data: "properties.dc:title",<br />readOnly: true,<br />renderer: orangeRenderer<br />},<br />

or a more advanced one that leverages the select2 editor:

<br />{<br />data: "properties.ipr:media_type",<br />editor: "select2",<br />select2Options: { // these options are the select2 initialization options<br />formatResult: getDefaultLabel,<br />query: function (query) {<br />getVocabularyData("dam_media_type", function (data) {<br />var results = [];<br />query.callback({<br />results: data<br />});<br />});<br />},<br />dropdownAutoWidth: true,<br />allowClear: true,<br />width: "resolve"<br />}<br />}<br />

You may notice the “data” mapping, with the json properties traversal. For select2, I use the automation API to fetch the values. Actually I have the same one for the JSF implementation of the suggest widget.

<br />function getVocabularyData(directoryName, callback) {<br />client.operation("Directory.SuggestEntries").params({<br />"directoryName": directoryName,<br />"localize":true,<br />"lang”:"en"<br />}).execute(function (error, data) {<br />callback(data)<br />});<br />}<br />

I also added an “afterChange” callback:

afterChange: function (change, source) {<br />if (change != null) {<br />for (var i = 0; i &lt; change.length; i++) {<br />listToUpdate[(myData[change[i][0]].uid)] = myData[change[i][0]];<br />}<br />ht.render();<br />}<br />}<br />

This allows me to store modified cells so I can save them for later and change the colors of the cells that have been updated, letting the user know what is going to be changed.

You should have a deeper look at the Handsontable documentation for discovering all that can be done. You can also refer to the Nuxeo JavaScript client documentation to understand how to add more interactions with the repository. Do not hesitate to share your experiences here!

The post A Spreadsheet Editor for Lists of Documents in the Nuxeo Platform appeared first on Nuxeo Blogs.

Introducing the EasyShare Plugin for File Sharing

Nuxeo has recently made publicly available a new plugin for our platform enabling easy file sharing from the platform to external recipients. We are using this internally to make our documents which we manage in our Nuxeo Platform intranet, available for our customers. The EasyShare Plugin is available on the Marketplace in addition to numerous other plug-ins, offering added functionality for the platform. It is easily installable directly from the Admin console of the Nuxeo Platform.

People often need to send files larger than possible by email, and they also need to keep control over access to these. This was either done by uploading the file to a system specific for sharing like Google Drive or Dropbox or creating an account in your ECM system. When your organization has your content managed within an ECM system it would be convenient to send and share directly from there with minimal configuration and maximum control.

The EasyShare plugin does just that. You create a share folder and either add files directly to it, or link by proxy to any other document within your platform. You can also specify an expiration date, a contact email and a comment visible to the recipient when they access the page. Instead of your recipient logging in, you send in any way you choose, a unique URL that goes directly to that share. Your recipient sees a web page and a listing of files, which they can download or permalink as well. That’s all there is to it.

 Let’s illustrate the use of the plugin

We first create an EasyShare Folder anywhere Folder types are allowed in the Nuxeo Platform. An expiration date allows you to specify the last day of the share availability. It will not disappear but will no longer be externally accessible. The Share comment is a message or description you’d like to have your recipient see on the landing page for the share. The contact email is the address visible on the share landing page as a contact for the recipient. Notifications of file download will also be sent to the recipient. This can be your own as creator of the share or another contact.

Image may be NSFW.
Clik here to view.
ES_Create

We then add files into the share. There are two methods. First, you can simply upload files into the share as in any folder within Nuxeo. Second, you can link other files anywhere in the system by browsing and adding to your worklist on left by drag and drop. Once you have a list of files you want to share, you navigate into the share folder you want to use. A new action below the list appears allowing you to add into the EasyShare. These are now proxies to the original documents.

Image may be NSFW.
Clik here to view.
ES_View

The URL to the Share folder is found on the URL Link button and pops up for cut and paste. This is the unique URL which is externally available without having to create any accounts in Nuxeo. It can be sent any way you want, by email, IM, etc.

Image may be NSFW.
Clik here to view.
ES_URL

You will also notice in the History tab that access and download events are logged with an IP to keep track of who has downloaded the shared files and when.

Image may be NSFW.
Clik here to view.
ES_Listing

Accessing the Share

Access to the URL takes you to the landing page for the share. The page displays the comments, contact email, share name and a file listing. It is simply a matter of clicking a file to download it. Communication with the share provider is made easier by a mail-to link on the page as well.

Image may be NSFW.
Clik here to view.
ES_External

Future

Since this is an initial release originally used for internal use at Nuxeo, we look forward to hearing user feedback on other features could be useful. We will continue to add on to the plugin over time and make it even more useful and comprehensive. The goal would be in the end to merge all the features implemented in this plugin with the newly released collection module that is part of the Nuxeo Platform and fully supported.

The post Introducing the EasyShare Plugin for File Sharing appeared first on Nuxeo Blogs.

Easy Nuxeo Platform Reporting with Kibana

As you may know we have added support for Elasticsearch to the Nuxeo Platform in the latest release, bring it greater scalability. We use it to index all the documents in your instance. The results outside of the scalability enhancements is a much better response time when browsing Nuxeo.

One of the other benefits of this integration is that we now have an easy to use reporting solution with Kibana. We talked about Kibana in a previous post about monitoring. Kibana lets you

visualize logs and time-stamped data.
Elasticsearch works seamlessly with Kibana to let you see and interact with your data.

So now you can very quickly and easily create custom dashboards to have stats about your documents. I like to add a histogram of all the dc:modified values of the documents. This gives me a very good idea of my instance activity. I usually also add the total of documents, a pie chart with some business values like the coverage or topic… And one of my favorites is the trend widget. It allow me to see the evolution of a query over time. I usually put a query for each workflow. Look at this screenshot to get a better idea.

Image may be NSFW.
Clik here to view.
Kibana Reporting

And the cool thing about Kibana is that the data is updated real time and filtered real time. Let’s say you are interested in a pic of activity on the histogram. Simply select the pic on the widget by dragging the mouse on it and it will automatically add a filter. Filters are automatically applied to every query. In the end, what you are really doing here is faceted browsing (outside of the webapp, but it’s coming).

Image may be NSFW.
Clik here to view.
Kibana Reporting Filtered

And the other good part is that setting up Kibana is dead easy. It’s simply an AngularJS application that queries Elasticsearch directly. So you just have to download it, deploy it on a web server and make sure the Elasticsearch address is correct in the configuration file. That’s pretty much all you have to do.

The post Easy Nuxeo Platform Reporting with Kibana appeared first on Nuxeo Blogs.

5 Ways to Get a Nuxeo Platform CoreSession

Recently Nuxeo has been updated internally to provide much better concurrency support when dealing with CoreSession, which is the main object through which developers manipulate documents. Along the way, some simplified APIs have been introduced to acquire and manage CoreSession objects, taking advantage of some Java 7 features.

Based on these updates, here is how you should now get a new CoreSession:

    try (CoreSession session = CoreInstance.openCoreSession(repositoryName)) {
        // do something with session, including session.save()
    }

This is using the Java 7 try-with-resource pattern, so you don’t have to explicitly do session.close(); - the try block does that for you. The above is equivalent to the following, which would have been used in Java 6 (but as Nuxeo only support Java 7 and above, the try-with-resource pattern is simpler and safer, as there’s no risk of forgetting to call close in a finally block):

    CoreSession session = CoreInstance.openCoreSession(repositoryName)
    try {
        // do something with session, including session.save()
    } finally {
        session.close();
    }

Keep in mind however that in most cases in Nuxeo a CoreSession is already available to you, and you don’t need to open one by hand.

Here are five ways to get a Nuxeo Platform CoreSession:

1. When writing an Automation operation, the CoreSession can be injected with:

    @Context
    protected CoreSession session;

2. When writing a Seam bean, the CoreSession can be injected with:

    @In(create = true, required = false)
    protected transient CoreSession session;

3. When writing a WebEngine module, the CoreSession is available from the ctx field using:

    CoreSession session = ctx.getCoreSession();

4. When writing a pure JAX-RS resource, you can do:

    CoreSession session = WebEngine.getActiveContext().getCoreSession();

5. If you already have a DocumentModel doc, it’s linked to a CoreSession, so you can always do:

   CoreSession session = doc.getCoreSession();

In all these cases, you’re accessing a CoreSession object that has already been allocated by the framework, and the framework is responsible for closing it, so you must not call close() on it.

Internally, this streamlining of CoreSession acquisition has enabled us to change the internals of the CoreSession.

A CoreSession is now thread-safe, because we’re now using a thread-local to manage the way the CoreSession is holding onto its internal Session object, which is the link to data storage. This is important in particular for our usage of the Seam framework, where a long-lived CoreSession is allocated for the duration of the conversation.

A CoreSession can also be used in a second transaction after you commit the first transaction that used it, if you’re using manual transaction start/commit.

All these changes are geared toward minimizing the number of surprises for the developer, and we hope that this goal has been attained.

The post 5 Ways to Get a Nuxeo Platform CoreSession appeared first on Nuxeo Blogs.

[Nuxeo Community] Meet Julie Lecomte

Image may be NSFW.
Clik here to view.
Julie Lecomte

I met Julie during the Documation Conference. She has been in the Nuxeo Community for a while now and we thought it was the perfect time to introduce you to her. Everyone please meet Julie Lecomte!

So Julie, we know you because you’ve been a customer for a while, you even gave a talk during Nuxeo World 2013. Could you please introduce yourself for our readers?

I’ve been studying to be an agronomist engineer, specializing in information system management. I have worked at the French Ministry of Agriculture since 2010. I was an infrastructure and document management project manager for the Ministry, so I was managing every Nuxeo instance there. That makes four instances (including GEDEI and GEDCourrier that I presented at Nuxeo World).

What do you do now?

Now, I am the manager of the local IS service at the departmental direction of the territories of Eure-et-Loir, which is part of the Ministry of Agriculture and the Ministry of Ecology. In my free time I’m putting together a partnership with my favorite company, Nuxeo, to offer consulting on Nuxeo Studio because I have a lot of practice to share in this area. And I’m also the deputy mayor for urban development/land use and technology in my city council.
Image may be NSFW.
Clik here to view.
AlleGED

Are you the one that recommended the choice of Nuxeo at the Ministry or did it happen just like that?

The choice was made when I arrived. Smile did a study in 2009 between Alfresco and Nuxeo. Nuxeo was a better fit for the Ministry’s needs. There was only one project when I arrived. Another one was being developed, and it had more and more success. Following this growing success, we started two other projects simultaneously: a tool to handle correspondence digitalization called GED Courrier and one to manage the creation, validation and dissemination of the Ministry instructions, GEDEI.

Your first project was to manage the second one?

I actually did everything on this one. Call me wonder woman [Laughs..]. This one actually took me the longest time.

The learning curve for Nuxeo Studio – when you arrived you didn’t know it, you had to learn everything.

Yes, I started working on the old project we had in early 2012. I had never used the Nuxeo Platform before. We had two Studio projects for our regular document management instances but it was really basic stuff, a bit of branding and not much else. There was already a lot of customization that was done outside Nuxeo Studio – customizations that we later migrated to Studio.

When I arrived everything was pretty much done. So in 2012, I started taking on the document management projects. I started looking at Nuxeo Studio late mid 2012, trying to figure out what we could do with it. And so I really started early 2013 when the two latest projects started. I followed the five day developer training given by Benjamin and Arnaud. And I survived :) Then, I mostly used the support.

Did you have to go outside Nuxeo Studio? Usually there is a small part of a project that won’t fit the Studio development model.

Well, actually the only thing we had to do outside Studio for the document management part was for the PDF merge but now it’s included in the latest version of Studio. So no.

We do have a WebEngine project which was not done with Studio, obviously. And also some URL management issues that we had to do outside, too. We also did a custom operation called by Studio to do a custom template rendering to add some business rules. It was not available at the time.

About the WebEngine application, what is it used for?

The application could be split in two parts, a backend and a frontend. The backend would be the document management part where we did customization with Studio, and for the frontend, the browsing part, we did a WebEngine project. The idea is to create and validate instructions in the backend and then browse them through the WebEngine application.

I am the Nuxeo Studio genie. I grant you three wishes. What do you want?

Something I would really like is to know when I am disconnected. Because after a long while, like a lunch break, your session ends and when you hit save, boom. You’ve lost the modifications you did on this tab. So it would be nice to be informed before it actually blows up.

And on the navigation part on the left, I have like 40, 50 automation chains. It’s hard to navigate between them.

But honestly, it’s ok. It’s a great tool. I am very happy with it.

Do you have any hobbies?

I am a dog trainer and I read a lot – like four books a week. If I had to choose one…that’s actually a hard question! If I really had to choose one, I would say the Anita Blake series.

Where do you live? Is it a cool place to visit?

I live in Chartres. Not much to do except visit the Cathedral. If you like the countryside then, yes, come and visit. But if you like activities, I can’t advise you to visit.

Image may be NSFW.
Clik here to view.
Cathédrale Notre-Dame de Chartres

Cathédrale Notre-Dame de Chartres
Licensed under CC BY 2.5 via Atlant

The post [Nuxeo Community] Meet Julie Lecomte appeared first on Nuxeo Blogs.

How to Create a Document Shortcut Using a Workflow

People Need to Collaborate…

You have probably encountered this situation: people need to collaborate on a document. Yet, they do not have access to each others space for security or confidentiality matters. You haven’t? Then you should read this blog post too! This is bound to happen to you at some point.

 …so Why Should We Restrain Them?

In such a situation, we often see some (bad) solutions:

  • Create a specific space for these users: It’s hard to keep track of what has been done, and to maintain. It also forces them to create a structure that has no other particular reason to exist.
  • Give access to the whole space where the document is located: If access was not granted in the first place, there was a reason for that.
  • Create several copies and merging them manually: Collaborating shouldn’t be that difficult.

So what should you do? Use Nuxeo Studio to create a basic workflow creating a document shortcut. If you are new to this, you can opt for a free 30 day Nuxeo Studio trial.

A Shortcut, You Say?

Shortcuts in the Nuxeo Platform are also called proxies. They can point to an archived version of a document, or to the document’s current version (in this case, we call it a live proxy).

How Does a Live Proxy Work?

  • Whenever you edit the original document or the proxy live, both are modified at the same time.
  • A live proxy inherits the access rights of the space where it is currently located. It doesn’t take into account the rights of the original document’s space. That allows people with access to different spaces to work together, and that’s the whole point of this post.
  • If the live proxy is deleted, it has no impact on the original document.

How Do I Implement That?

We will use a workflow to ask your user where they want to have a live proxy created, from a predefined options list. The result in Studio is the following:

Image may be NSFW.
Clik here to view.
Create shortcut workflow graph

Looks easy, right? On to the recipe now!

Define Where the Proxy Can Be Created

We will start by creating the options list for the proxy creation.

  1. In Nuxeo Studio, add a new vocabulary.
  2. Choose “simple vocabulary”. In this example, I named it “spaces”.
  3. When you add entries:
      1. In the id: put a relative or absolute path. This will point to the space where the proxy can be created. In the capture below I put a relative path starting from the domain.
      2. In the label, type what the user should see in his options list.

    Image may be NSFW.
    Clik here to view.
    Destination spaces vocabulary

We are using a vocabulary to achieve this for two reasons:

  1. If we provided the user with a document suggestion, he would only see spaces where he has access to.
  2. It gives us better control over what we want to display.

Create Your Workflow

  1. In Nuxeo Studio, create a new workflow and name it.Image may be NSFW.
    Clik here to view.
    Create shortcut workflow - variables
  2. In the variables tab, add a String variable named destination. This will store the user’s choice.
  3. In the availability tab, define when you should be able to use your workflow. Make sure you choose “Current document is: Regular Document” to avoid people launching the workflow on a proxy. For more details, have a look at the filtering options reference page.
  4. In the graph tab, drag and drop a “start” node, a “stop” node, and an “approve” node from the node library on your left. Link them together. Your setup should look like this:

    Image may be NSFW.
    Clik here to view.
    Create shortcut workflow graph

Setup the User’s Choice

The user should be presented with the list of destination spaces. Here’s how.Image may be NSFW.
Clik here to view.
Create shortcut workflow - Destination selection form

  1. Hover your mouse on the “approve” node and edit it.
  2. Go to the form tab.
  3. In the drop down list on your right, choose your workflow variables (var_yourWorkflowId).
  4. Drag and drop the “destination” variable to the form in the middle of the screen.
  5. A popup will appear to let you choose the display properties.
  6. Use a single directory suggestion widget, and use your “spaces” vocabulary. You can also setup the “minimum characters” property to 0.
  7. Make sure you save these properties before continuing.

Implement the Business Logic

  1. In the node’s “general” tab, you can setup the properties as follows:Image may be NSFW.
    Clik here to view.
    Create shortcut workflow - General properties

    As you can see, I am using an automation chain in the node’s output to create the shortcut. Click on the Create button to add it, and don’t worry: this will save your workflow automatically.
  2. You can build your chain as follows:Image may be NSFW.
    Clik here to view.
    Create shortcut workflow - Create live proxy chain
    Image may be NSFW.
    Clik here to view.
    Create shortcut workflow - Create live proxy chain destination details

    The destination path for my live proxy is based on the current domain’s path, to which I add the user chosen option. You could build it differently of course.

Try It Out

You are all done! Now deploy your changes and try them out:

  1. In your local Nuxeo instance, go to the admin center.
  2. Choose the update center menu on the left.
  3. Click on the “Nuxeo Studio” tab, then on the “update” button.
  4. And this is the final result:Image may be NSFW.
    Clik here to view.
    Create shortcut workflow - Final result
    Image may be NSFW.
    Clik here to view.
    Create shortcut workflow - Final result - task

My next post will explain how to delegate temporary access to a document. See you soon!

The post How to Create a Document Shortcut Using a Workflow appeared first on Nuxeo Blogs.


Using REST API to Start a Workflow

The following video demonstrates using a REST API call to run a Nuxeo Operation that will start a workflow process on a document.

Some concepts and tools you’ll see:

  • The REST API explorer tool that Nuxeo provides to allow you too see all the different REST calls available, and execute them.
  • A view of all Operations and their descriptions, available on the Nuxeo server.
  • A REST call for an operation and how to set required parameters in a JSON object.
  • A view of Workflow in our sample Case Management application.

The post Using REST API to Start a Workflow appeared first on Nuxeo Blogs.

Export Your Nuxeo Tree Structure to Your File System

I work with a customer that needs to export the Nuxeo document tree to a file system daily. This was a perfect opportunity to implement a multi use case  document exporter. The code is available on GitHub, and we will add it to the marketplace soon.

Plugin Organization

This plugin enables the user to export one chosen root structure of documents in Nuxeo to a specified File System repository.

The installation of the plugin will add a new operation in “Services” called “ExportStructureToFS”. This operation must be added to the registries in Studio and then can be used in an automation chain.

The JSON path is the following:

{ "operations" : [
      { "category" : "Services",
        "description" : "This operation enables to export the structure contained in the Root
name path to the File System Target path. You can choose to export deleted documents or not
and You can declare your own query to choose the document being exported",
        "id" : "ExportStructureToFS",
        "label" : "ExportStructureToFS",
        "params" : [ { "description" : "",
              "name" : "Root Name",
              "order" : 0,
              "required" : true,
              "type" : "string",
              "values" : [  ],
              "widget" : null
            },
            { "description" : "",
              "name" : "File System Target",
              "order" : 0,
              "required" : true,
              "type" : "string",
              "values" : [  ],
              "widget" : null
            },
            { "description" : "",
              "name" : "Query",
              "order" : 0,
              "required" : false,
              "type" : "string",
              "values" : [  ],
              "widget" : null
            }
          ],
        "requires" : null,
        "signature" : [ "void",
            "void"
          ],
        "url" : "ExportStructureToFS"
      } ] }

 

By default, the following rules are implemented:

  • All documents of the chosen structure are exported,
  • When a document exported is already existing in the File System directory, it will be prefixed with a timestamp. This way, no document will be deleted,
  • Attached files to a document are exported to the same directory as the document. They are prefixed with the name of the document parent.

This plugin can be customized in different manners:

  • By changing the default query used to retrieve the documents to be exported. The query can be changed by modifying a parameter of the operation – this can be done in Studio.
  • By using the defined extension point “exportLogic” and by using the existing contribution or by defining a new contribution for export. This contribution requires some Java code.

Default Behavior

Image may be NSFW.
Clik here to view.


The operation “ExportStructureToFS” has the following parameters:

  • Root Name: The root name of the structure of the Nuxeo Platform that will be exported.
  • File System Target: Where the export will be done on the File System.
  • Query: An optional parameter. By default the query called by the exporter is: SELECT * FROM Document ecm:mixinType !=’HiddenInNavigation’ AND ecm:isCheckedInVersion = 0 AND ecm:currentLifeCycleState !=’deleted’.

By default, all documents don’t have the facet “HiddenInNavigation”, are non-version and are not in the ‘deleted’ state will be exported.

Customization 1: Changing the default query

If you want to change the list of documents that will be exported, you can define your own query and put it the in the Query parameter of the “ExportStructureToFS” operation.

For example, if you want to export all the documents, even the ones in “deleted” state, you can define this query in the field of the query parameter:

SELECT * FROM Document WHERE ecm:mixinType !=’HiddenInNavigation’ AND ecm:isCheckedInVersion = 0

To create your own query, you can take a look at the documentation page on the NXQL language that is used.

Customization 2: Using the extension point

If you want to change the export mechanism, the extension point “exportLogic” can be contributed with a custom class. For example, you might want to:

  • Override existing documents (don’t use the timestamp prefix approach),
  • Create an XML export of each document (provided as an example).

The following contribution has been implemented as an example: “CustomExporterPlugin”. It provides the default export (export all the documents under root name) and in addition, for each document exported, creates the XML version.

You can use it with the following XML extension in Studio :

<extension target="org.nuxeo.io.fsexporter.FSExporter" point="exportLogic">
		<exportLogic class="org.nuxeo.io.fsexporter.CustomExporterPlugin" />
</extension>

Scheduling an Export

If you want to schedule the export, you can use a cron and schedule the call of the the Automation chain using cURL, or use the Nuxeo Platform internal cron service.

The post Export Your Nuxeo Tree Structure to Your File System appeared first on Nuxeo Blogs.

How To Grant Temporary Access to a Document Using a Workflow

In my last blog post, I explained how to give permanent access to a document using a shortcut (a.k.a. live proxy). But what if you simply want to delegate temporary access, and keep control over who you will give access to? Then you can also use a workflow.

Giving Temporary Access

In a workflow, temporary rights can be granted when you assign a task on a document. The goal is normally to let users achieve some work on a restricted document. In this example we will be taking advantage of this possibility.

The workflow initiator will first select users he wants to delegate access to, and for what duration. Then, we will assign the selected users a task, thereby granting them temporary access. Of course this task is merely created for technical reasons. We won’t ask the users to actually achieve something, but we will still display them a “revoke” button. Clicking this button will end the task and the workflow, removing their access during the process.

For security reasons, we will also assign a task to the workflow initiator. The goal is to let him review who he gave access to, and eventually revoke their access by clicking on a button. Finally, an escalation rule will be added. Past the specified duration, this rule will apply automatically and end the workflow.

To build this workflow, we will make use of Nuxeo Studio. Reminder: you can try Nuxeo Studio for free!

The final result looks like this:
Image may be NSFW.
Clik here to view.
Temporary Access Workflow - Final Graph

And here is the step by step method to achieve it.

Create Your Workflow

  1. In Nuxeo Studio, create a new workflow and name it.
  2. In the variables tab, create the following variables:
    1. days (Integer). This will store the access duration.
    2. delegates (String, multivalued). This will store the chosen users list.

Image may be NSFW.
Clik here to view.
Temporary access workflow variables

Start Designing Your Graph

  1. In the graph tab, drag a start node and a simple node from the node library on the left.
  2. Link them together.
  3. Save your work.

Configure User Selection

  1. Hover your mouse on the simple node and edit it.
  2. In the general tab, fill in the information as following:
    Image may be NSFW.
    Clik here to view.
    Temporary access workflow - User selection general tab
  3. In the form tab, select var_yourWorkflowId in the dropdown list on the right.
  4. Drag and drop the delegates and the days variables.
  5. You can set the properties as in the captures below.
    Image may be NSFW.
    Clik here to view.
    Days Widget
    Image may be NSFW.
    Clik here to view.
    Delegates Widget
  6. The user will need buttons as well, to cancel or confirm his choice. Scroll down to add them, then fill in their id and label:
    Image may be NSFW.
    Clik here to view.
    User Selection Buttons
  7. Now save your work. Reminder: you need to save the node’s properties and the workflow when you are back in your graph tab!

Update Your Graph

If the user confirms his choice, then we will create two tasks:

  • For the selected users, to grant them access and let them revoke it, and
  • For the workflow initiator to revoke the users’ access.

Let’s update our workflow to reflect that.

  1. Drag and drop a stop node.
  2. Link the cancel transition to it. Now if the user clicks on cancel, it will end the workflow.
  3. Drag a fork 2 ways node.
  4. Link the confirm transition to it.
  5. Edit it, and go to its transitions tab. Rename the transitions with users_revocation and initiator_revocation for better clarity.
    Image may be NSFW.
    Clik here to view.
    Fork Transitions
  6. Drag a multiple tasks node. Link it to the users_revocation transition.
  7. Drag a simple task node. Link it to the initiator_revocation transition.

Good! Now your graph should look like this:
Image may be NSFW.
Clik here to view.
Graph Before Revocation Config

On to the next step.

Configure Workflow Initiator Revocation

The workflow initiator should be able to know who he granted access to and for how long. Also, he should be able to revoke their access if necessary. That’s the purpose of the task we created for him. Let’s get it done.

  1. Edit the simple task node linked to the initiator_revocation transition.
  2. In the general tab, configure it as following:
    Image may be NSFW.
    Clik here to view.
    Initiator Revocation General 1
    Image may be NSFW.
    Clik here to view.
    Initiator Revocation General 2

    Note that the due date expression matches the date after which access will be removed automatically. This is meant to display in the task how long access is delegated.
  3. In the form tab, we will display the selected users. Drag and drop them, and make sure they are shown as read only.
    Image may be NSFW.
    Clik here to view.
    Initiator Revocation Form 1
    Image may be NSFW.
    Clik here to view.
    Initiator Revocation Form 2
  4. Don’t forget to add a revoke button!
    Image may be NSFW.
    Clik here to view.
    Revoke Button
  5. Save your work (both the node and the workflow) and proceed with the next task.

Users Revocation Configuration

  1. Edit the multiple tasks node linked to the users_revocation transition.
  2. Setup your general tab as following:
    Image may be NSFW.
    Clik here to view.
    User Revocation General 1
    Image may be NSFW.
    Clik here to view.
    User Revocation General 2

    It is extremely important to fill in the grant permission to task assignees field here. This will determine which access you want to give to the chosen users. In this case, I am giving Read access, but you could choose to give Write access or any other possibility. Note that the same right will be given to all chosen users.
  3. Make sure to copy the node id, as you will need it later.
    Image may be NSFW.
    Clik here to view.
    Node Id
  4. We will take this opportunity to replace the default button and transition provided by this node as well.
    1. In the form tab, add a revoke button, and remove the default approve button.
      Image may be NSFW.
      Clik here to view.
      Remove Approve Button
    2. In the transitions tab, remove the approve transition.
      Image may be NSFW.
      Clik here to view.
      Remove Approve Transition

Note that this is a multiple tasks node. To end the task and revoke access, all users with delegated access need to click on the revoke button. That’s why we will setup an escalation rule in order to remove access automatically past a certain date.

Setup automated access removal

  1. While you are still in this multiple tasks node, head to the escalation rules tab. Configure it as following:
    Image may be NSFW.
    Clik here to view.
    Escalation Rules Definition
    Image may be NSFW.
    Clik here to view.
    Escalation Rules Condition
  2. The escalation rule will now launch a chain past the specified date. Which chain, you ask? Well, we didn’t add it yet. Click on the create button on the right side of the screen and name it.
  3. Your chain should be composed of the following operations and parameters:
    1. Fetch > Context document(s)
    2. Workflow Context > Get open tasks
      1. nodeId: paste the node id you took from the general tab earlier.
      2. processId: @{Context["workflowInstanceId"]} This one can be inserted easily using the dropdown list in the editor.
    3. Workflow Context > Complete task
  4. Save your chain. One last detail remains and you will be all set.

Finalize your graph

  1. Go back to your workflow.
  2. In the graph tab, drag two stop nodes. Link your tasks to them. Your workflow should now look like this:
    Image may be NSFW.
    Clik here to view.
    Temporary Access Workflow - Final Graph
  3. Save your work.

There you go! This example is very generic but you can adapt it to your needs and improve it. Let us know in the comments or in answers if you want more details about it.

The post How To Grant Temporary Access to a Document Using a Workflow appeared first on Nuxeo Blogs.

Using QR Codes with the Nuxeo Platform

How many times did you encounter these little things?

Image may be NSFW.
Clik here to view.
nuxeo-qrcode

QR Codes? What for?

They are QR codes. Using a dedicated application, you can scan them with your smartphone to display data, go to a specific URL and so on. So, what use could you have of them in your Nuxeo application? Well, a QR code can easily be generated with any document metadata. Here are a few use cases that come to mind:

  • As a sales executive: Scan a QR code displayed in a customer document type to get a vCard imported into your phone contacts.
  • As any company representative: Build a QR code from your Nuxeo profile information, to use on your business card.
  • As any company member: Generate QR codes from a document’s metadata. For example, include the Nuxeo permanent link to the file itself. Great for documents that get printed.

Many possibilities exist for QR codes.

Integrating QR Codes – the Need for a Pluggable Architecture

Okay, but what if everyone comes asking for something different? Will you spend hours maintaining each implementation, feeling as if you’ve opened Pandora’s box? Not at all: that’s when the Nuxeo platform’s pluggability comes in handy.

The Nuxeo platform contains many services. Every service implements business logic around a specific Nuxeo functionality. And almost all of them include one or more extension points. These extension points are sort of interfaces. You can feed them with XML files to:

  • Change the service behavior,
  • Add new entries,
  • Deactivate functionality you do not need.
  • etc…

That’s exactly what you do when developing in Nuxeo Studio: build XML in a graphical interface.

In some specific cases though, the default platform features do not cover your needs. The QR codes generation is a perfect example of such a situation. But even then, it’s no big deal, because you can plug your own service and extension points into the platform. This allows further configurability to your business logic.

An Extension Point for QR Codes Generation

Back to QR codes. By implementing a service along with its extension point,  you can contribute simple XML files. One for each usage. If your implementation needs to evolve, you can refactor your code as much as you like. The generic logic is in the service, and your business use cases described in the XML contributions. Doesn’t that sound nice and clean?

Look at the XML below. This is an XML contribution using my personal implementation:

<extension target="org.nuxeo.sample.MyQRCodeService" point="qrcontent">
  <qrcontent id="titleVersion">
    <separator value="||" />
    <xpath value="dc:title" />
    <xpath value="uid:major_version" />
    <xpath value="uid:minor_version" />
  </qrcontent>
</extension>

It contains:

  1. An id for my configuration,
  2. The metadata to include in my QR code (on top of the document id), and
  3. A character (or chain) to separate each metadata.

And here is the resulting QR code on a random document:

Image may be NSFW.
Clik here to view.
QRCode-HelloWorld

Want to Learn More about QR Codes Generation?

During our integration training, we already cover the Nuxeo development basics. The QR codes generation example is now added to it for developers willing to go further. It’s a fun and useful way to learn some advanced Nuxeo theory by practicing, at least in our opinion.

Do you want to know more, or try it out?

Also, make sure to have a look at the zxing and QRGen libraries that I used for this example, they truly make QR codes generation a breeze.

I look forward to discussing this with you during a training session!

The post Using QR Codes with the Nuxeo Platform appeared first on Nuxeo Blogs.

Nuxeo Drive iOS Edition Available in the iTunes Store

We have great news today. Nuxeo Drive Mobile (iOS) Edition is available in the iTunes Store for all you iPad users out there. And if you’re a developer, you can also get the sources on GitHub.

I know you’re very curious, so I’ll start right off with screenshots:

Image may be NSFW.
Clik here to view.
Browse Your Synchronized Documents

Browse Your Synchronized Documents

The iPad app is optimized for Nuxeo Platform 5.9.3+. With this app, you can browse the Nuxeo Platform, open all the documents compatible with iPad native apps or using the iOS previewer.

You can also synchronize part of your content to your device for easy offline access. Typical use cases are the synchronization of Sales force documentation resources or QA procedures and standards.Image may be NSFW.
Clik here to view.
Smart&Soft

It has been developed by our friends and partner Smart&Soft. They develop kickass apps for every major mobile platform out there. They even open sourced their Android and iOS frameworks, android4me and iOS4me.

Nuxeo Drive Mobile Edition is also a good way to understanding what can be done with our iOS SDK. Which brings me to our last Nuxeo Tech Talk Meetup – it was about iOS. We invited Smart&Soft to present their activities and how they worked with our SDK to build Nuxeo iOS Drive Edition.

Then Arnaud presented the iOS SDK he developed for the Nuxeo Platform. His presentation was a bit more technical. He showed us the code and explained which choices he had too make and how Matthias helped us.

The post Nuxeo Drive iOS Edition Available in the iTunes Store appeared first on Nuxeo Blogs.

Viewing all 161 articles
Browse latest View live