Get the content id of a new item

I am implementing an extension that saves large files (think multimedia) directly to the NAS as opposed to the Rhythmyx database. The extension in question is implementing IPSRequestPreProcessor. I would like files saved in a folder according to their contentid (to make it unique so other users will not be able to override the file by uploading the file with the same name)

This works great when the content item in question is already created (and thus has a contentid). The issue that I am running across is when you create a new item, it does not have a content id. Creating a pre-processor or even a post-processor does not seem to help in that initial submission (ie. pre-processor: user uploads file -> i don’t know its content id / post-processor: user uploads file->file saved in db -> i know content id and can move the file to the appropriate location, but how do i resubmit the form with the updated information?)

I can think of a hack to do it (ie. implement a pre-processor transformer that fires on every WF action that 1. puts the file in a temp directory on the first upload and marks a hidden field 2. cleans up that file if the content id is known and updates the hidden field) but I would much rather see an elegant solution…if there is one… :slight_smile:

Does anyone have any suggestions?

Thanks in advance,
Jit

Jit,

I cannot promise you an “elegant solution”, but I have had to do something like this in the past.

What we did was create 2 extensions, a pre-processor and a post-processor.

The pre-processor identifies the incoming request, and if the request is one that we want to defer, it removes the object from the request parameters (to prevent the content editor from updating that field) and then builds a request Private Object. (see the JavaDoc for IPSRequestContext.setPrivateObject() and getPrivateObject()).

The post-processor looks for the private object and performs the deferred processing. At this point IPSRequestContext.getParameter(“sys_contentid”) will contain the content id of the newly inserted item.

Since the “key” for the private object is by convention a String, make it unique using the normal Java package naming conventions (e.g. edu.vt…)

Recently, whenever I’ve had to do this, I’ve tried to “wrap” the request to Rhythmyx in some alternative User Interface, so that we can make appropriate calls to Rhythmyx via the API rather than using the standard UI and placing “hooks” in the server.

However, if all you are doing is moving one field into an external storage area, then the pre and post processor approach is probably cleaner than building an alternate interface.

Dave

Thanks for the reply Dave,
I had gone down a similar path of pre-processing / post-processing (which led me to the question about the log…http://forum.percussion.com/showthread.php?t=2451). I guess I do not fully understand the proposed solution. From what i grok, the pre-processor runs before submitting items into the database and the post-processor runs after the item has been submitted. Storing the file via “setPrivateObject()” is elegant in terms of: i do not need to store a temp file, however my problem will still be i need to update another field that “points” to the correct location of the file.

I know you mentioned “deferred processing” and while i see how this would apply to moving the file to the correct location, how would i update the other field?

I could use the privateObject in the post-processor as well to run some function in a preprocessor that could fire off after any workflow action (ie store the file location, then in the pre-processor check if that object exists, and if it does, update the field accordingly), of course the key would probably be the contentid to prevent modification by anything else (ie if they upload multiple files/new items)…

Thanks again,
Jit

Jit,

The sequence of events (somewhat simplified, of course) for a content editor request is:

  1. Server parses incoming request, authenticates the user, builds the parameter map, etc.

  2. Pre-processor extensions run. These extensions may modify the parameters that will be seen by the handler.

  3. A “Handler” runs. In the case of a new item or an edit of an existing item, this is the “Modify Handler”. There are separate handlers for Workflow and other operations. The handler builds an XML document

  4. Post-processor extensions run. These extensions may modify the XML result document.

  5. An XSLT stylesheet is applied to the XML, which produces the HTML page.

  6. The HTML is displayed to the user, and the request terminates.

Any private objects that you attach to the request disappear once the request is finished. You can also attach private objects to the “Session” (which lasts as long as the user is logged in).

If your Post-Processor extension must modify the content item, you have to be extremely careful. Calls to the Rhythmyx API (e.g. IPSContentWs) will cause a new request to be generated (for the same content editor application) and your pre-processor and post-processor extensions will be called for this new internal request. This can lead (very quickly) to a Stack Overflow if you don’t take steps in your extensions to detect and avoid recursive loops.

In your case, I think you’d be much better off creating a unique ID for your files outside of Rhythmyx, and the placing this ID in a field (with IPSRequestContext.setParameter()) in the pre-processor extension.

Dave

Dave,
I agree. While it was a great idea to use the content id, I think I will have to come up with another unique way to identify files independent of RX. I am thinking of probably some sort of hash between the timestamp and the user name would give me what i want.

Thanks for all your help! I am certain that I will need to use a session private object in the future…

Jit

Jit,

While you can do some sort of hash function, the only way to really guarantee uniqueness is to use a counter, and the simplest way is to use the database for this.

Rhythmyx exposes its internal counter mechanism via the IPSGuidManager.createId() function.

If you call this function with an arbitrary “key” name, you will get the next number in that sequence. Use any string you like (up to 50 characters), but I suggest something like “edu.vt.NASFileKey” just so that is no possibility of name collisions.

This is the same mechanism that Rhythmyx uses to allocate new content ids.
Look at the NEXTNUMBER table in the database, and you’ll see how it works.

Dave

Dave,
Thanks,
That is just what I was looking for!

Jit

I’ve uploaded our implementation of saving files to the nas. Please look at the readme for how to use it.

The solution that we came up with was to implement a pre-process/post process extension.