My Mullet Business Card

I recently had to redesign my business card and decided to take a step back and think about the different functions it serves at different times. What resulted was my new mullet cards: business in the front, party in the back.

A business card can be much more than just a means to contact you at a later time.

It’s a way to connect with people on a personal level

At networking events I notice that people often jump to the address when handed a business card in order to strike up a conversation about people or places they know near there.  There’s a good chance we have a lot more in common than that so I threw several work and personal interests in a sort of thin word cloud.  Maybe they’re an avid cyclist, maybe they’ve just started coworking, or maybe they want to blow off this networking event and go get a good beer.

Who the hell was this and why do I have their card?

If I don’t process (I use CardMunch) the cards I’ve collected at an event with 24 hrs (which I usually do) I often can’t place a person by their name or company alone if I didn’t have more than a brief conversation with them.  My interests might help someone recall who handed them the card, but a face will almost certainly do the trick.  Realtors usually have a headshot on their cards, why shouldn’t I?

Use QR codes wisely

QR codes are meant to ease entry and access for mobile devices.  Often people put all of their contact info in one QR code in something like a vCard format, which can work, but when you try to put all of your information in a single code it can greatly affect the ability of QR readers recognize it, especially in bad lighting.  Even if the vCard does get captured it most often gets neatly tucked away in their address book, never to be viewed again.

I chose instead to go with two simple codes; one that is the URL for my About Me page, and one that is my Google Voice number.  If I’m telling someone how cool Untappd is or discussing cycling routes they can quickly snap the About Me QR code I just handed them and get right to my Untappd or RunKeeper profiles from there.  If weeks later they find my card and decide they want to chat they can snap the Call Me code which is only the phone number so most readers will just ask for a quick confirmation then dial directly, no hunting through address books.

Don’t buck the trend too much

The front is pretty much your traditional card with basic contact info.  Obviously not everyone knows what a QR code is, let alone how to read them, or is going to want to look at my ugly mug. Business in the front.

A shout out to the printers

I used MOO.  I was very impressed with the ease of submitting and verifying, speed of printing and shipping, and quality of the final product.  They did a fantastic job and I highly recommend them.

This was a good first pass, I’ll probably modify them a bit for the next round.  Do you have any suggestions?

Categories: Uncategorized

Inconsistent CMIS Query Results? It’s not You, It’s your Locale.

A simple CMIS query like:

SELECT D.* FROM cmis:document AS D WHERE D.cmis:name LIKE '%Flower%' OR D.cmis:contentStreamFileName LIKE '%Flower%'

was giving me a fit lately, not working at all in RightsPro‘s CMIS plugin which uses OpenCMIS and yielding inconsistent results in CMIS Workbench where re-posting the same query ten times would give the expected result maybe half the time.

Thanks to Florian Müller and this post, it seems as though Alfresco doesn’t always behave as expected when the locale is set in the CMIS session.

Removing the locale session parameters got things working in RightsPro, but I didn’t immediately see an easy way to change the locale in a Workbench session (the log shows that it’s using a default of en_US), and I still don’t know what’s up with the inconsistent results there, perhaps a coincidental caching issue.

This was all using OpenCMIS 0.3 against Alfresco Enterprise 3.3.1 over SSL.

Searching Custom Aspects via CMIS

20110212 2 comments

I didn’t immediately see any simple, working examples of how to search custom aspect properties via CMIS so I’ll post a brief one here.

The Aspect

In this example we’re using a CMIS query to search for the IPTC caption property provided by the IPTC/EXIF project. After installing that module the properties are applied using an aspect which is defined in $ALFRESCO_HOME/WEB-INF/classes/alfresco/module/iptcexif/model/iptcModel.xml.

Within that file you’ll see:

    <aspects>
      <aspect name="iptc:iptc">

The Query

In our case the target Alfresco repository is running enterprise 3.3.1 and aspects are implemented via JOIN syntax as very briefly stated in the wiki.

So the resulting query for this particular search of the IPTC caption field ends up looking like:

SELECT D.*, IPTC.* FROM cmis:document AS D JOIN iptc:iptc AS IPTC ON D.cmis:objectId = IPTC.cmis:objectId WHERE IPTC.iptc:caption LIKE '%searchTerm%'

The Changes

There were big changes in Alfresco 3.4 in terms of metadata extraction and I haven’t yet had a chance to update the forge projects (or determine if they’re still even needed) and there are proposals for aspects in the next CMIS spec so I’ll be back to update this post.

Categories: Alfresco, CMIS Tags: , , ,

MyFaces Tomahawk and the HTML BASE Tag

This one incited a bit of facepalm.

When trying to changing part of RightsPro‘s header implementation to use the HTML BASE tag the element seemed to be ignored completely and resource references were still relative to the page URL.  The tag was present, correct, and closed, but having no affect.

It turns out the BASE tag must appear ‘before any element that refers to an external source’ but MyFaces Tomahawk adds any script references needed immediately after the opening HEAD tag, rendering the BASE tag useless.

I don’t have time to modify the Tomahawk source at the moment for a proper fix but did submit a bug.

As a workaround you can put the BASE tag above the head element. It’s not valid HTML but most browsers will still obey it and render the page properly.

A short post, but it may save a few precious hairs from being pulled out. I’ll update if and when the bug is resolved.

Categories: Uncategorized

Spring @Configurable With AJDT Compile-Time Weaving

I know, that’s a honey of a title, but you found this didn’t you?

Anyways, after some house cleaning and re-organizing of the projects that make up RightsPro in Eclipse I found that domain objects annotated with Spring’s @Configurable annotation were no longer having their dependencies injected when running the app in tomcat or when running AbstractTransactionalDataSourceSpringContextTests unit tests.

Turns out I must have removed the AspectJ library during re-organization and added it back in which also seemed to wipe out the AspectJ Build settings in the project properties.  When AspectJ does its compile-time weaving it doesn’t know anything about the @Configurable annotation unless you add spring-aspects.jar to the Aspect Path tab in the AspectJ Build settings.

F yeah, magical aspects are back in business.

Categories: Java, Spring Tags: , , ,

Render Me This: Video Thumbnails in Alfresco 3.3

20100623 2 comments

Alfresco has undergone quite a few changes under the hood in version 3.3, including refactoring of the ThumbnailService to make use of the RenditionService, which I had to explore in a recent deep dive to get video working for the thumbnails extension. This is obviously a subject dear to your heart as well or you would have moved on by now.

Alfresco 3.1.

Let’s take a look at how things worked back in the old days, before 3.2 (fuzzy 2009 dream sequence begins…)

You most likely kicked things off with a thumbnail generating URL which would hit a ScriptNode.createThumbnail method which looked up the thumbnailDefinition and called the ThumbnailService with the TransformationOptions contained in the definition.

The ThumbnailService then told the ContentService to perform the transformation which looked up the ContentTransformer from the TransformerRegistry and executed transformer.transform which usually delegated to a RuntimeExec object to perform the actual command line transformation.

If we were to visualize the key elements of that stack for a synchronous video thumbnail creation it would look something like:

  • org.alfresco.repo.jscript.ScriptNode.createThumbnail
    • org.alfresco.repo.thumbnail.ThumbnailRegistry.getThumbnailDefinition (loads TransformationOptions)
    • org.alfresco.repo.thumbnail.ThumbnailServiceImpl.createThumbnail
      • org.alfresco.repo.content.ContentServiceImpl.transform
        • org.alfresco.repo.content.transform.ContentTransformerRegistry.getTransformer
        • org.alfresco.repo.content.transform.ContentTransformer.transform
          • TempFileProvider.createTempFile
          • org.alfresco.util.exec.RuntimeExec.execute
            • ffmpeg …

Well now, that’s not so bad.

Alfresco 3.3.

These Alfresco people don’t mess around. If it’s determined that refactoring should happen, it happens, real damn quick, even if it’s huge. To that end subsystems were rolled out in 3.2 and the RenditionService was introduced in 3.3.

Subsystems. Certain content transformers, like ImageMagick, have been refactored as a subsystem, which is cool. Read the wiki page to get the full story but in short it’s a much more flexible architecture.

The ffmpeg video transformer contained in the latest release of the thumbnails extension follows this precedence and has been refactored as a subsystem, so there.

RenditionService. I wouldn’t say I hate it, but this package should be wary of eating crackers in bed, or maybe I’m just not familiar enough with it yet.

The new rendition service utilizes RenditionDefinitions which require that any TransformationOptions be ‘serialized’ into a parameter map, which are then reassembled into TransformationOptions objects before being passed to the ContentTransformer. I suppose this is done to make it easier to do things like hand renditions off to another server in a cluster, but it’s a bit of a pain in the ass for developers.

So, back to our synchronous video thumbnail creation scenario (deep breath), the ThumbnailService now creates a RenditionDefinition which it passes to the RenditionService which wraps things up in a PerformRenditionActionExecuter that gets passed to the ActionService. The PerformRenditionActionExecuter calls the ActionService again which loads the RenderingEngine from the spring ApplicationContext. A RenderingEngine is itself an ActionExecuter so the ActionService calls execute which calls render which proceeds to rebuild the TransformationOptions object needed by the ContentService to get the proper ContentTransformer so transformer.transform can use a RuntimeExec object to perform the actual command line transformation.

The key elements of our pseudo stack/method trace would look like:

  • org.alfresco.repo.jscript.ScriptNode.createThumbnail
    • org.alfresco.repo.thumbnail.ThumbnailRegistry.getThumbnailDefinition (loads TransformationOptions)
    • org.alfresco.repo.thumbnail.ThumbnailServiceImpl.createThumbnail
      • org.alfresco.repo.thumbnail.ThumbnailServiceImpl.createRenditionDefinition
        • org.alfresco.repo.thumbnail.ThumbnailRegistry.getThumbnailRenditionConvertor().convert(transformationOptions, assocDetails) <- this serializes the transformationOptions into a parameter map
      • org.alfresco.repo.rendition.RenditionServiceImpl.render
        • org.alfresco.repo.rendition.RenditionServiceImpl.createAndExecuteRenditionAction
          • org.alfresco.repo.action.ActionServiceImpl.createAction(PerformRenditionActionExecuter.NAME)
          • set the renditionDefintion on performRenditionAction
          • org.alfresco.repo.action.ActionServiceImpl.executeAction
            • org.alfresco.repo.action.ActionServiceImpl.directActionExecution
              • load ActionExecuter from applicationContext
              • org.alfresco.repo.rendition.executer.ImageRenderingEngine.execute
                • org.alfresco.repo.rendition.executer.ImageRenderingEngine.render
                  • org.alfresco.repo.rendition.executer.ImageRenderingEngine.getTransformationOptions <- rebuilds parameter map into TransformationOptions objects
                  • org.alfresco.repo.content.ContentServiceImpl.transform
                    • org.alfresco.repo.content.transform.ContentTransformerRegistry.getTransformer
                    • org.alfresco.repo.content.transform.ProxyContentTransformer.transform <- subsystems
                      • org.alfresco.repo.content.transform.ContentTransformerWorker.transform
                        • TempFileProvider.createTempFile
                        • org.alfresco.util.exec.RuntimeExec.execute
                          • ffmpeg …

that’s a spicy meatball!

A while ago we submitted an issue to Alfresco suggesting TransformationOptions which contain distinct target AND source options so that one could for example specify that all ‘doclib’ thumbnails be of max-width X and max-height Y (the type of target options currently available) and furthermore, if it’s a document take page 1 (or maybe you need a different page in your deployment) or if it’s a video take 1 frame starting 0.5 seconds in, or if it’s a layered image file take the second layer, etc. (a list of source options).

Alas, this concept of SourceTargetTransformationOptions hasn’t yet been embraced by the Alfresco team but is used by the video transformer in the thumbnails extension which made refactoring for renditions even more difficult, but you’re not here to listen to me bitch and moan, so I’ll just say that it’s done and seems to be working fine.

So, there you have it, renditions and subsystems as they relate to video thumbnails. Hit me up with any questions or things I’ve missed.

Daemontools and File Permissions

Contegix turned me on to daemontools which is a great way to manage services you need to keep alive.  A great use for it is managing multiple Apache Tomcat instances which can each be easily be configured to run under different users with different options.

I was recently running into a problem where a webapp running in Tomcat didn’t have access to a particular directory mounted via fuse.  I could verify that the user Tomcat was running under had access to the directory by logging in as that user then creating a file there.  WTF?

Turns out the run script being used for the Tomcat service was using the daemontools program setuidgid, i.e.

exec setuidgid ${USER+"$USER"} ./bin/catalina.sh run

and the daemontools manual for that program states that it removes “all supplementary groups“.  Doh!

The Tomcat user’s access to this particular directory is in fact granted based on a secondary group membership and in this case should really stay that way.  setuidgid only allows a single user argument that’s used for both the user and group so I couldn’t change the running group and there’s no option to keep the user’s secondary groups.

Instead I opted to use su instead of setuidgid which leaves the secondary groups intact and gave the desired access to the directory:

exec su ${USER+"$USER"} -c "./bin/catalina.sh run"

Run catalina, run.

Categories: Deployment Tags: , ,
Follow

Get every new post delivered to your Inbox.