Showing posts with label CoreService. Show all posts
Showing posts with label CoreService. Show all posts

Sunday, March 03, 2013

The rise of the corporate team player (good old TOM)

In case it isn't clear by now, I'll make it explicit: I love the Tridion Object Model API. Sure, our content delivery API is nice, and OData on the content delivery rocks.But me and the TOM was love at first sight (even if TOM never really acknowledged or even winked at me, I'm fine with this one-sided relationship). TOM has matured quite a lot in the past few years, moving from an extremely flexible COM+ architecture to a semi-functional .NET implementation (TOM.NET) to a fully functional one (with Tridion 2011) and with its WCF, service-oriented face ("CoreService") it just shines.

One of the intended benefits of adding a WCF face to TOM was to open up access to our Content Manager core to any client you would want to implement yourself or ourselves (for instance, the Content Manager Explorer and Experience Manager interfaces of our new soon-to-be-released Tridion 2013 use the CoreService to talk to the core), but a few things happened - perhaps unintended initially - with this new-found freedom to interact with Tridion: customers started looking at the CM as something that other applications can talk to.

And Tridion has one functionality that most other applications lack: it can push content to your website. Any type of content. At any time of the day. And though I wouldn't recommend using Tridion to push your 70 million transaction records to your website hourly, it actually fits really well if you don't need to republish your full catalog all the time (which typically is a sign of a bad architecture to start with, but let's not go there). A decoupled WCM will always have trouble with pushing time-sensitive information - like updating the price of 1700 products in the next 2 seconds while at the same time publishing your new 7000 pages website. But we have no trouble at all pushing product info to the website. Even if we don't manage it - or even know it exists beyond perhaps a SKU or product ID.

And I'm not the only one to have realized the potential of this. One of our customers is now routing all 3rd-party content via Tridion (through WCF) for editorial review and publishing to the website, something that was particularly painful for them to do before Tridion was added to the picture. Another one is considering using Tridion as the publishing mechanism for some "records stored in Oracle" that don't need editor attention - but do need to end up on the website, and that's hard to do with their current system. Yet another customer is looking at providing access to Tridion from their PIM, so "collections" of products can be published directly from the PIM's interface (while having Tridion do the heavy lifting).

This flexibility to play nice in the Enterprise is becoming more & more key to today's always on, always connected "modern enterprise" that must deal with aging products that are incredibly hard to upgrade or modify to cope with "simple things" like publishing to a website. But when all it takes is to call a webservice, upload a stream or structured content, and ask Tridion to "Please publish this to our Live site", the whole game changes. Suddenly, it's not black magic anymore to get something on the website.

And I love that too. EAI was my playground before Tridion, and now Tridion is providing EAI-lite features (don't hold your breath on having Tridion handle your bank transactions just yet, but as a publishing service provider for your internal tools it is awesome).

In a recent discussion with a customer we were debating whether to import product info into Tridion or keeping it where it is. The customer's architect was inclined to placing it all in Tridion, while we were telling them not to - probably a surprising action from a vendor, telling a customer to "not use our software to store your info" - but we had a really good reason for this: Tridion is not a PIM. It was not built as a PIM. It does not think as a PIM. So use your PIM for PIM-like tasks.
Likewise, your PIM is not built to publish stuff to the Web or manage it once its live. So don't use your PIM to publish to the web, just ask Tridion to do it for you.

I guess I may be quite a geek, but this idea of using software for what it was built, and talk to other software so they can complement each other, feels just like poetry to me. :-)

PS - It turns out the architect's previous experience with WCM was with a very large competitor of SDL, which has notorious problems playing nicely in the enterprise, and that's why he thought he would have to import all content into Tridion first. He has seen the light now!

Saturday, January 26, 2013

My Tridion VM bootstrap project

As part of my luxurious and privileged seat in Tridion Product Management I get to test new stuff all the time. It's great to just point my browser to the build server and download the latest nightly build (stable or unstable) and start playing around with it - how's the notification area behaving? Can I assign tasks now? How's the workflow engine doing? etc.

While this is great, it has a certain, heavy, repetitiveness to it. Every time I get a new build I need to either completely uninstall Tridion and start again (we obviously don't bother doing migration scripts between minor builds) or start from a completely new VM.

And this means:
  • Create new blueprint
  • Create new schemas
  • Create new content
  • Create new publication target(s)
  • Configure Content Delivery for HTTP Upload
  • Configure Website
  • Configure Session Preview/Experience Manager
Even the most adept Tridion professional will recognize that this takes a LONG time to set up, and all to be destroyed soon, since a new build comes in tomorrow.

So I started, slowly, creating a series of C# command prompt programs to automate stuff for me. Initially these scripts would just create my diamond-shaped blueprint, a set of schemas, and some components. Then, I added a script to import content via RSS so I get some real content in it. Then, I expanded it to also create pages for these components. Then I added configuring the Publication Targets and Target Types. Then I added expanding the Tridion pre-build web applications and copying the configuration for these. Then I added actually creating the sites in IIS. Then I added support for all this to be configured via a XML file. Then I added changing the default templates to include Experience Manager building blocks. And finally I added support for Tridion 2011 too.


And now I decided to share it with everyone. The two projects I use to prepare my environments are available under MIT license on Google code.

There are 2 projects in here: CreateAnEnvironmentForMe and ImportContentFromRss. Each does what its name implies, and there's reasons why they are separate which I won't care to elaborate. I also offer no support whatsoever and really just hope the community can help evolve this solution to something a bit more stable. This code is not intended to be used in Production Environments, and there's no guarantees it will work for you.

These tools are tools I use, and they're fit for me to use them. If you need more rounded corners to use it, please feel free to change it - contact me via this forum or the google project if you want committer rights on the project. I typically run these projects from within Visual Studio, because I expect them to fail here and there, and this allows me to quickly fix them.

Hope this project can help others out there.

Friday, September 23, 2011

Recursing through Group Members with the Core Service

Yesterday I had to write a simple method to get me a list of all users who are members of a given group, using the Core Service.

Obviously, this is one of those tasks you'll immediately classify as "simple" or "easy" or "low complexity". Which is probably true, if you happen to have done this before...

Only one added twist, the list should contain all users who are members of this group, including sub-groups (groups members of the same group).

In TOM.NET this is a trivial foreach(Trustee trustee in group.Members), but in CoreService-land (and WCF-land) we don't have the Object Model available, only the data model. So I had to twist my mind for a while to get this to work, but eventually got it working as follows.

public Dictionary<string, string> GetUserEmailsByName(GroupData group)
{
    Dictionary<string, string> result = new Dictionary<string, string>();
    GroupMembersFilterData groupMembersFilter = new GroupMembersFilterData();
    foreach (XmlNode groupMemberNode in _coreServiceClient.GetListXml(group.Id, groupMembersFilter))
    {
        TrusteeData trustee = (TrusteeData)_coreServiceClient.Read(groupMemberNode.Attributes["href", Constants.XlinkNamespace].Value, ReadOptions);
        if (trustee is UserData)
        {
            if (trustee.Description.Contains("@"))
            {
                string userDescription = trustee.Description;
                string userEmail = UserEmailRegex.Match(userDescription).ToString();
                userDescription = userDescription.Replace(userEmail, "").TrimEnd();
                userEmail = userEmail.Replace("(", "").Replace(")", "");
                if (!result.ContainsKey(userDescription))
                    result.Add(userDescription, userEmail);
            }
        }
        else if (trustee is GroupData)
        {
            Dictionary<string, string> subMembers = GetUserEmailsByName((GroupData)trustee);
            foreach (string key in subMembers.Keys)
            {
                if (!result.ContainsKey(key))
                    result.Add(key, subMembers[key]);
            }
        }
    }
    return result;
}

The hard part to figure out was how to get the list of "Members" for this group, since GroupData does not expose that information:

_coreServiceClient.GetListXml(group.Id, groupMembersFilter)

Adding one more to the bag of CoreService patterns...