Month: October 2020

Display a chart in Alfresco Share: Part Two

In Part One, you saw how to create an Alfresco Share dashlet that uses out-of-the-box Aikau widgets to chart data. In that example, the data came from a repository tier web script.

In this blog post, Part Two, you’ll see how to fetch the data from an external API called from the Share tier. The external API could be anything, but for this example we’ll implement it with Spring Boot. We’ll add a Docker module to the project so that the Spring Boot application will run in a container alongside the Alfresco and Share containers that are part of all Alfresco SDK projects. Finally, we’ll secure the external API so that only authenticated Alfresco users can invoke it.

Steps

This code is available in GitHub. Just like Part One, each of the steps below is tagged. After you clone the repository you can switch between steps by doing git checkout step4 or git checkout step5 etc. I’m starting with “Step 4” because Part One covered steps 1 – 3.

If you are going to follow along, and you haven’t already, clone the project:

git clone https://github.com/jpotts/alfresco-share-chart-example.git

Step 4: Add an external REST API with Spring Boot

If you are following along:

git checkout step4

The existing code invokes a web script in the repository tier that returns sales data. A more likely case is that the sales data comes from a REST API running external to Alfresco. In this step we’ll build a small Spring Boot application that simulates the external sales data API. To make things simple, we’ll add the new application as an additional module to the alfresco-share-chart-example project.

Switch to the root of the alfresco-share-chart-example project and create a new directory named alfresco-chart-example-api.

Within that, add a new pom.xml file that pulls in the Spring Boot dependency:

There are many ways to organize a Spring Boot app. I like to create separate files for my application, model, controllers, and services:

We’ll set the application port to 8000 in the application.properties file:

Test by switching into alfresco-chart-example-api and running mvn clean install. Then, run java -jar target/alfresco-chart-example-api-1.0-SNAPSHOT.jar. Once the app comes up you should be able to invoke:

http://localhost:8000/api/salesData

And see the JSON response.

Use ctl+c to stop the application.

Step 5: Create a Docker module for the example API

If you are following along:

git checkout step5

The Alfresco SDK uses Docker to run Alfresco and Alfresco Share, so we’ll do the same. To do that, create a new module directory called alfresco-chart-example-api-docker.

Within that, add a new pom.xml file. This pom.xml pulls in the application created in the previous step as a dependency so that it can be easily copied to the Docker image.

Now add a Dockerfile that builds the image. There are a lot of ways you can deploy Spring Boot apps with Docker. In this example, we’ll just use an Alpine Linux image with the JDK, and launch the Spring Boot app directly from the JAR, just like you did when you tested the app in the previous step.

When we start Alfresco with the run.sh script that is included with the SDK it builds the Alfresco containers, starts them up, and networks them together using Docker Compose. Our container should be included in that, so we’ll update the Docker Compose file that already exists off the root of the project source code and add corresponding tasks to the run scripts:

Finally, make sure to add the two new module directories to the root pom.xml:

Test by changing to the alfresco-chart-example-api-docker directory and running mvn clean install. Then, switch to the root of the project source and run ./run.sh reload_api or run.bat reload_api. This should cause a Docker container to start up with the Spring Boot application running. Again, you should be able to invoke:

http://localhost:8000/api/salesData

And see the JSON response.

Run ./run.sh stop or run.bat stop to stop the container.

At this point you should be able to do ./run.sh build_start or run.bat build_start to start up Alfresco, Alfresco Share, and the Spring Boot Example API, all at once.

Step 6: Update Share to fetch data from the API

If you are following along:

git checkout step6

Now Alfresco, Share, and the API are running, but the Share chart dashlet is still pulling its data from the repository tier web script. It’s time to update the dashlet to instead pull its data from the Spring Boot example API.

First, create a web script that the chart dashlet will call to get its data. This is similar to the one we created in the repository tier in Part One, but this one is going into the Share tier. You could run this in the repository tier, but putting it in the Share tier saves us one hop.

The web script calls the external API and returns the data in the format that the dashlet is expecting. To make that call, we’re using a built-in root-scoped object called “remote” that is able to call external REST APIs:

var connector = remote.connect("example-api");
var dataString = connector.get("/api/salesData?ticket=" + ticket);

That connector ID, “example-api”, refers to Share configuration that includes the actual host that is being connected to:

In this example, the API is running as a Docker container, so the endpoint-url refers to the Docker Compose service name:

<endpoint-url>http://alfresco-chart-example-api:8000</endpoint-url>

Finally, the CustomReportService we created in Part One is still referring to the repository tier web script. It needs to be updated to instead call the new Share tier web script:

You’ve made changes to Alfresco Share, so do ./run.sh reload_share or run.bat reload_share to rebuild and run the Share container. When it comes back up, go to Share at http://localhost:8180/share, log in, and go to the test site that has your chart dashlet.

The chart dashlet should now display data coming from the Spring Boot API.

Step 7: Secure the API to only allow requests from authenticated Alfresco users

If you are following along:

git checkout step7

The Alfresco Share sales summary dashlet is now pulling data from an external REST API. If you don’t mind that anyone can fetch that data from the REST API at any time, there is no need to go any further. In this example, let’s assume that only authenticated Alfresco users should be allowed to retrieve data from the REST API. How can we modify the API and the web script that calls it to meet that requirement?

First, let’s add a new service to alfresco-chart-example-api that knows how to validate Alfresco tickets:

The service uses the Alfresco 5.2 public REST API to ask Alfresco if the ticket is valid.

With that in place, the SalesDataController can be updated to validate the ticket before returning a response:

If you do a run.sh reload_api or run.bat reload_api at this point and try to invoke http://localhost:8000/api/salesData you should see a 401 returned, which is exactly what we want–if you don’t have a valid ticket you cannot invoke the sales data API.

To test a successful call, use curl to grab a ticket:

jpotts@Metaversant alfresco-share-chart-example % curl -X POST -H 'content-type: application/json' http://localhost:8080/alfresco/s/api/login -d'{"username":"admin", "password":"admin"}'
{
    "data":
    {
        "ticket":"TICKET_01b44089022f98740c3eb27009f49e787f9fb213"
    }
}

And then pass the ticket to the sales data API and the response should be successful:

jpotts@Metaversant alfresco-share-chart-example % curl "http://localhost:8000/api/salesData?ticket=TICKET_01b44089022f98740c3eb27009f49e787f9fb213"
[{"region":"North","amount":125},{"region":"South","amount":125},{"region":"East","amount":125},{"region":"West","amount":125}]

So far, so good.

The last step is to modify the Share tier web script that fetches the sales data from the API to pass along the ticket. One gotcha here is that Share does not have direct access to the ticket, so we’ll first add a tiny repository tier web script that returns the ticket:

And then we can modify the Share tier web script to fetch the ticket from the repository tier and pass it along to the sales data API:

The controller uses the same “remote” root-scoped object it used previously, but it relies on the default connector, which is the Alfresco repository web script connector, to fetch the ticket:

// Need to get the user's ticket from the repo
var ticketString = remote.call("/custom/ticket");
var ticketResponse = jsonUtils.toObject(ticketString);
var ticket = ticketResponse.ticket;

// Get the sales data from the API
var connector = remote.connect("example-api");
var dataString = connector.get("/api/salesData?ticket=" + ticket);

You’ve now made changes to both the repository tier and the share tier. Either reload each one with ./run.sh reload_acs and ./run.sh reload_share or do a ./run.sh stop to stop all the running containers followed by a ./run.sh build_start to start everything back up.

That’s it. You’ve now got an external API that returns data only to authenticated Alfresco users and a Share dashlet that displays that data in a pie chart.

Display a chart in Alfresco Share: Part One

The other day a customer asked how much trouble it would be to chart some data in an Alfresco Share dashlet. The data comes from a non-Alfresco REST API.

The answer is that it is relatively easy to do. That’s because Alfresco Share ships with some basic out-of-the-box chart widgets called BarChart, DonutChart, and PieChart. You may have seen examples of dashlets that use PieChart if you’ve ever added the Site Content Breakdown or Site Contributor Breakdown dashlets to your Share dashboard.

In this blog post, I’ll show you how to make your own chart dashlets by shamelessly stealing Erik Winlöf’s code that implements the Site Content Breakdown dashlet and modifying it for our own purposes to show sales data, by region, in a dashlet. In part one, the data is fetched from a repository tier web script. In part two, the data comes from a Spring Boot app.

Steps

This code is available in GitHub. Each of the steps below is tagged. After you clone the repository you can switch between steps by doing git checkout step1 or git checkout step2 etc.

If you are going to follow along, clone the project:

git clone https://github.com/jpotts/alfresco-share-chart-example.git

Then, checkout step0:

git checkout step0

And startup the project using Docker and Docker Compose:

./run.sh build_start

This will start up Alfresco using Docker with no customizations made at this point.

Step 1: Add a simple API to return the data to chart

If you are following along:

git checkout step1

If Alfresco is already running:

./run.sh reload_acs

We want to build a dashlet that can chart data fetched from an API source. So, to start, we’ll add a repository tier web script that returns data as JSON. Once the chart is working we can swap that out to an external data source.

The files that make up the web script are:

With the web script in place, invoking http://localhost:8080/alfresco/s/custom/data will return a JSON response with sales broken down by region, like this:

     {
         "resultset": [
           [
                 "West", 125
             ],
             [
                 "North", 75
             ],
             [
                 "East", 250
             ],
             [
                 "South", 150
             ]
         ],
         "metadata": [
             {
                 "colIndex": 0,
                 "colType": "String",
                 "colName": "name"
             },
             {
                 "colIndex": 1,
                 "colType": "Numeric",
                 "colName": "sum"
             }
         ]
     }

The format of the JSON is what the chart component expects–it includes a resultset property, with a list of data values, and a metadata property, which describes the data types found in the result set.

If you need exact steps on how to create a web script, see my webscripts tutorial.

Step 2: Add a dashlet

If you are following along:

git checkout step2

If Alfresco is already running:

./run.sh reload_share

In this step, add a dashlet. Share supports the old “Surf” way to add dashlets as well as the newer “Aikau” way to add a dashlet. Because we’re going to use an Aikau widget for the chart, we’ll use the Aikau approach for the dashlet.

Dashlets are implemented using web scripts, so we’ll need a descriptor, controller, and view template:

This is an Aikau dashlet, so in addition to the dashlet web script, we need an Aikau widget, implemented in client-side JavaScript, that sets up the dashlet:

Now log in to Share at http://localhost:8180/share, create a test site, and customize the site’s dashboard to add the newly-created dashlet.

Customize dashlet page

It doesn’t have anything in it yet because we need to define a service to fetch the data and a widget to display it. That’s the next step.

An empty dashlet

Step 3: Add a widget and a service

If you are following along:

git checkout step3

If Alfresco is already running:

./run.sh reload_share

The last step is to add an Aikau service to fetch the data and an Aikau widget to display the data fetched by the service. The widget will use the out-of-the-box pie chart widget to display the chart.

First, we write an Aikau service to fetch the data from the API and publish it to a topic:

Then, we write an Aikau widget that subscribes to the topic and renders the chart using the PieChart widget:

The dashlet controller we implemented earlier needs to be updated to refer to the new service:

And the Aikau dashlet code needs to be updated to point to the new widget:

Now when the dashlet renders, it fetches the data from the repository tier web script and presents it in a pie chart.

Hovering over each slice in the pie chart produces and overlay with the detailed data.

Share dashlet with a pie chart that pulls data from a REST API

Part Two Preview

In Part Two, we’ll create a little Spring Boot application that the dashlet will call to fetch its data instead of fetching it from the repository tier. The Spring Boot app will authenticate the request using the authenticated Alfresco user’s ticket, so that only authenticated Alfresco users can fetch the data from the API.

Q & A with OpenText’s James McGourlay

Photo of a big question markI had the opportunity to ask James McGourlay, OpenText Executive Vice President, Operations, a few questions about this week’s announcement that OpenText would begin offering support for Alfresco Content Services.

What follows is a list of questions I submitted to James followed by his answers, which I unfortunately received after the deadline we had agreed to for the publication of my blog post on the subject.

Jeff Potts: OpenText has many large ECM platforms and products in its portfolio. Alfresco is as complex as many of those. What can you point to that establishes your ability to support mission-critical workloads on such a complex platform, especially given that no one associates “OpenText” with “Alfresco”?

James McGourlay: OpenText knows ECM and Content Services. We specialize in supporting and maintaining enterprise software for mission critical systems at many of the largest organizations in the world. As such, we also have the global infrastructure and systems to provide enterprise-class services for docker installs/containerization, global call-intake, service level targets, etc.

Jeff Potts: The press release says that, “OpenText has put in place a dedicated team to manage and contribute to the Alfresco open source community”. How big is that team? What types of roles do you have on that team? e.g., First-level support? Engineers? Are there any community managers on the team? Will the team be developing new features? Or is the focus exclusively on bug fixes?

James McGourlay: We developed this service to help customers – including joint OpenText and Alfresco customers – protect their investment and get the most out of their Content Services. Level one support is not our focus. Our offering starts at level 2 support, with seasoned, experienced professionals that know how to set up environments and do detailed service. Our support professionals have been doing sustaining maintenance for enterprise software for 20 years or more in many cases. They are expert on trouble shooting, patching, enhancing, and releasing patches and fixes to provide support through level 3.

Jeff Potts: The OpenText fact sheet says: “All open source fixes are submitted to the community for consideration in the next release. OpenText will maintain the fixes it submits until they are confirmed in an Alfresco Community Edition release.” What does “fixes are submitted to the community for consideration” mean? How will that happen? Where will the fixes be maintained? In a publicly accessible repository? Will this be run as a public open source project? Has OpenText ever submitted any fixes/changes to Alfresco? Do you anticipate any hurdles given that Alfresco Software, Inc. employs 100% of the Alfresco committers?

James McGourlay: Any code we develop that is derivative work of Alfresco Community Edition we will submit through the Alfresco community committer program. It will be up to the Alfresco community to act on this work or not. However, we will maintain all our fixes in the OpenText OpenSource Edition for Alfresco, that will be available to our customers that subscribe to the OpenText OpenSource Support for Alfresco program. It will not be publicly available.

We have not yet submitted fixes, as we are just launching this service this week. Any bugs we identify we will report via the issue tracker and we will submit our proposed fixes to the community. We are also looking to complete fixes as requested by our customers. We hope that Alfresco will treat the fixes we submit as any other community submission and it will be up to the community to determine if they also believe there is value there.

Jeff Potts: Will OpenText provide any features to the community that are currently only available to Alfresco Software’s enterprise edition subscribers?

James McGourlay: Our intention is to enhance the community edition based on the needs of our customers that subscribe to the OpenText OpenSource Support for Alfresco program. So, our customer needs will be the driver of all changes and enhancements we make.

Jeff Potts: Will OpenText make its branded edition of Alfresco Content Services freely available under an OSI-approved license? Or will it only be available to paying OpenText customers?

James McGourlay: As mentioned previously, while we’ll submit fixes and enhancements to the community, our OpenText OpenSource Edition will only be available to customers that subscribe to the OpenText OpenSource Support for Alfresco program.

There you have it

So, although OpenText got these answers to me nearly a day past the deadline, at least they did eventually respond to every question posed, which I really appreciate.

For the community, we now know for sure this is a private fork, but it is good to see that OpenText will contribute fixes via Alfresco Jira. That could be a good thing.

Their plan to offer support sounds dubious, but the mention of “joint” OpenText and Alfresco customers is sensical…if they have customers who have both products, why not offer to support both. I’m still skeptical that an Alfresco-only customer would ever consider it, but we’ll see.
Photo credit: Big Question Mark, by Benjamin Reay

OpenText offers to support Alfresco customers

Barn with dubious sales pitchOpenText announced this week that it would begin offering support for Alfresco Content Services. The announcement comes about a month after Hyland Software announced their intention to acquire Alfresco Software, Inc. (see my blog post).

UPDATE: After the original publication of this post, OpenText got back to me with answers to my questions. I’ve updated the post to reflect that, and I’ve posted the Q&A verbatim, here.

Alfresco sells services and support for their software, Alfresco Content Services (ACS), which includes a handful of features available only to those who purchase a license. In addition, Alfresco Software distributes a “community” edition of ACS freely-available to everyone under the Apache License.

Both Enterprise & Community Edition

Based on the announcement, OpenText will provide paid support to both enterprise and community edition customers. But if someone is already paying for support for enterprise edition from Alfresco Software, why would they pay an additional maintenance fee to OpenText, a competitor, for support of that same software? It’s hard to imagine how a customer would be able to justify that.

Providing support for community edition makes more sense. Alfresco does not offer any kind of support for community edition beyond what customers can get by reading forums and blog posts, and Alfresco actually forbids its partners from selling support and services around community edition. OpenText will try to fill that gap.

There is already a large community of non-partner service providers who have built businesses providing professional services to both enterprise edition and community edition customers (Disclosure: I am one). The challenge for OpenText is that they have yet to establish any credibility regarding their ability to provide support for Alfresco. They are trying to convince customers that they can basically walk into the room cold and throw enough resources at any problem to resolve it successfully.

The press release hints at how they will do this, saying, “OpenText has put in place a dedicated team to manage and contribute to the Alfresco open source community”. How big that team is, who it is comprised of, and what exactly they’ll be doing is not discussed in the announcement. So I reached out to James McGourlay, OpenText Executive Vice President, Operations, and that Q&A can be found here. The short answer is that the goal of the team is to provide level 2 support by leveraging OpenText’s experience in other ECM platforms to address Alfresco issues.

How will they collaborate with the community?

OpenText’s announcement may sound like they want to participate in the community, but when one of the community’s leaders asks to hear more about their plans, they aren’t forthcoming. So, we can only judge them by their actions. An Alfresco employee with visibility into the company’s issue tracking system confirmed earlier this week that OpenText has never filed a single issue, which is the generally accepted mechanism one would use to contribute fixes to any open source code base. I’ve never seen them at an Alfresco conference, in a chat room, or in the forums. That does not sound like a company that is ready to engage the community.

I reached out to OpenText to ask them how their community contributions are going to work. You can read the full Q&A here. OpenText says they have not yet filed any issues because they have only just launched the service. They plan to contribute fixes back to Alfresco via the Community Contributor Program.

Their own Alfresco distribution will not be public

If OpenText plans on “contributing to the Alfresco open source community” exactly how they plan to do that is important for the community to understand. OpenText says they are offering their customers a branded release of community edition. Branding is easy enough to add, but is it a fork? If you read the fact sheet that OpenText provides, it sheds a little more light:

“All open source fixes are submitted to the community for consideration in the next release. OpenText will maintain the fixes it submits until they are confirmed in an Alfresco Community Edition release.” –OpenText

This sure sounds like OpenText will maintain their own fork of Alfresco and that they will contribute changes to Alfresco for inclusion, upstream. It will then be up to Alfresco Software, Inc., for whom 100% of the ACS committers work, to decide whether or not to merge those fixes.

The key question for the Alfresco community is whether the OpenText fork will be a private fork or a public fork that they will run as a true open source project? If it is a private fork, then this isn’t really about open source or the community at all–this is instead about OpenText taking a marketing jab at Hyland and Alfresco. If it is going to be a public fork, well that would be huge news. Alfresco has always kept its community at arms-length when it comes to commitorship. But I highly doubt that OpenText, a proprietary behemoth who has existed on a steady diet of other proprietary ECM vendors (Documentum, Interwoven, Hummingbird, RedDot, Vignette…), is looking to start and invest in an open, collaborative ecosystem based on one of their competitor’s products.

After publication of this post, OpenText confirmed that they will maintain a private fork of Alfresco, distributed to their paying customers, so there will be no opportunity for the community at large to collaborate. However, the community might ultimately benefit from the contributions OpenText makes.

So is this all just snake oil?

At Alfresco DevCon, an online conference that took place online in August, John Newton, Alfresco’s founder and CTO, made an off-hand comment about going after OpenText and how great it would be to take them down, especially after they “captured” Documentum, a company he also founded. I could be wrong, but this announcement from OpenText just smacks of marketing chicanery aimed at throwing FUD into the market surrounding the Hyland acquisition, and basically telling John, “If you want some, come get some”.

Photo Credit: Snake Oil, by Eddie McHugh