Sunday, 22 December 2013

Tracing who the Final Approver was on a UCM Workflow Document

All workflow history "Approves/Rejects" etc is stored in the OCS database. Heres a quick way to track it with metadata.

Quick Steps:
  • Open Workflow Admin Applet
  • Criteria tab
  • Select Workflow from list
  • Click on the final Step on the right
  • hit Edit
  • Click Events tab
  • Hit the Edit button on the Exit event
  • Click the Custom tab on the pop up window
  • Tick Custom Script Expression
  • Copy paste the following code
<$if wfAction like "APPROVE"$>
<$wfUpdateMetaData("xComments", "Final Approval By: " & dUser)$>
<$endif$>

** You can change the xComments field to any metadata field you have set in Config Man that is applied to a Document.

*** dUser will put the username eg (rudderb) for me but I believe its possible to do the following
<$executeService("GET_USER_INFO")$>
<$name="USER_INFO"$>
<$var = rsFirst(name)$>
<$loopwhile getValue(name, "#isRowPresent")$>
<$wfUpdateMetaData("xComments", "Final Approval By: " &  getValue(name, "dFullName"))$>
<$var = rsNext(name)$>
<$endloop$>
EDIT: The above works! I just tested it.

PDF Watermark Internal error: Unexpected Exception (null) during saveTemplate

For whatever reason, it seems that its impossible to change Watermark Templates in the PDF Watermark Administration Applet. Everytime I try I get the above error.

But a work around for this is as follows:
Note the Content ID, if you do a quicksearch for that Content ID you should be able to find and Check Out the .HDA file which contains all the settings defined in the PDF Watermark Administration Applet.

The HDA should contain the following resultSets:
@ResultSet PdfwTextWatermarks
13
text
location
rotation
alignment
fontName
fontSize
fontWeight
fontColor
layer
pageRange
pageRangeModifier
x_coord
y_coord
@end

@ResultSet PdfwImageWatermarks
8
imageID
location
layer
pageRange
pageRangeModifier
x_coord
y_coord
scaleFactor
@end



Add in your settings into these resultSets in the typical HDA fashion and upload the .HDA file as a new revision.

Once you have uploaded your template as a new revision your changes will be immediately reflected in the PDF Watermark Administration Applet.


Cause:
I'm not 100% on the reason this is all buggered up but I suspect one of the following two reasons:

  1. IdcService=PDFW_SAVE_NEW_TEMPLATE contains bugs
  2. idcToken pdfwUserPassword LocalData parameters are blank in the Templates HDA file (though I think it'd be poor practice to have to include these).

Tuesday, 17 December 2013

WSDL to execute SQL against the WebCenter Content/UCM Database

This is handy to get into the guts of the UCM Database and allows you to extract data that isn't available from the Standard IDC Services.

Just remember some data is stored in HDA files in ucm/cs/data and might not be accessible via SQL.

Download the HowToComponents and install DatabaseProvider Component or Download the Component Directly

You can use the following WSDL I created in the WSDL Generator.

** Note you might have to change the following part of the WSDL
<soap:address location="http://localhost:16200/_dav/cs/idcplg" />
to be your UCM Servers Address

Thursday, 5 December 2013

Running UCM/WebCenter Content Applets from Linux

On windows you can navigate the UCM installed application and run Content Server Analyzer/Component Wizard etc from Explorer. But on OEL there is no Desktop Manager installed (most cases) so to run these Applets you must use Xterm.

1.       Run MobaXterm
2.       Type “ssh -X oracle@ucmserver” in the main window
3.       cd to the UCM directory /cs/bin/ from memory on server its “/oracle/Middleware/domains/user_projects/ucm/cs/bin” (or close to it)
4.       Dir of the directory should look like
5.       Then type ./<ToolName> 

and voila! The app is now running

javax.security.auth.login.FailedLoginException: [Security:090303]Authentication Failed: User weblogic weblogic.security.providers.authentication.LDAPAtnDelegateException: [Security:090295]

If you are receiving this error then you probably have an External Authentication Provider set to REQUIRED in Weblogic > Server Security Realm

to fix this:
  1. SSH into the Machine
  2. CD to the Admin server directory eg. /u01/app/oracle/admin/<DOMAIN>/aserver/<DOMAIN>/
  3. nano /config/config.xml
  4. search for <sec:control-flag>REQUIRED</sec:control-flag> near the top of the XML
  5. Check that the <sec:name>ActiveDirectoryAuthenticator</sec:name> matches the name of one of your Providers
  6. Change the value to "SUFFICIENT"
Try running ./startWebLogic.sh again

Thursday, 21 November 2013

Syncing Active Directory Groups with UCM Aliases

So I was required to find a way to drive Approvers in UCM by Active Directory groups (nightmare!) after some deliberation and a few meetings the simplest solution in my mind was a link between Active Directory Groups and UCM Aliases.

If we could link these lists together then we could have the LDAP server as the source of truth for who belongs in the Alias. And thus a component was born. I extended some CIS code from Jonathan Hult and creating a Filter on the following two services
IdcService=LOGIN
and
IdcService=GET_SEARCH_RESULTS
When a user executes these services custom java code compares the current users Groups agains the Alias list in UCM. If theres a match The user is added to the group!

heres a link to the component!

JAVA: Reading Weblogic Username/Password from the boot.properties file

In order to create a JMX connection to the WLS you must provide a username/password. If you are deploying a webapp to the server and want to read the properties you can use the following methods.

public Map init() {

Map<String, String> userCredentials = new HashMap<String, String>();
       //FIND THE PATH THIS CLASS FILE IS DEPLOYED TO
      Class cls = this.getClass();
      String path = cls.getProtectionDomain().getCodeSource().getLocation().getPath();
      String decodedPath = "FAIL";
       //STRIP THE PATH BACK TO /servers/
try {
              decodedPath = URLDecoder.decode(path, "UTF-8");
             decodedPath = decodedPath.substring(0, decodedPath.indexOf("/servers/"));
     } catch (Exception ex) {
             System.out.println(ex);
     }
//Change domain to aserver from mserver -- DEPENDING ON YOUR DOMAIN SETTINGS
      String domain = decodedPath.replaceAll("mserver", "aserver");

      //GET A STRING OF THE CONTENTS OF THE BOOT.PROPERTIES USING THE readBootProperties method
            String[] wlsbootProperties = readBootProperties(domain);
            String username = "";
            String password = "";
            //Find Username / Password strings
                     for (int i = 0; i < wlsbootProperties.length; i++) {
                if (wlsbootProperties[i].indexOf("username") > -1) {
                    username = wlsbootProperties[i];
                } else if (wlsbootProperties[i].indexOf("password") > -1) {
                    password = wlsbootProperties[i];
                }
            }

            //Strip back to GET AES STRINGS
            username =
                    username.substring(username.indexOf("{AES}"), username.length());
            password =
                    password.substring(password.indexOf("{AES}"), password.length());


            try { //CLEAN OUT BACKSLASHES
                while (username.indexOf("\\") > -1) {
                    username = username.replace("\\", "");
                }
                while (password.indexOf("\\") > -1) {
                    password = password.replace("\\", "");
                }
                           //DECRYPT
                String decryptUser =
                    new weblogic.security.internal.encryption.ClearOrEncryptedService(weblogic.security.internal.SerializedSystemIni.getEncryptionService(domain)).decrypt(username);
                           //DECRYPT
                String decryptPass =
                    new weblogic.security.internal.encryption.ClearOrEncryptedService(weblogic.security.internal.SerializedSystemIni.getEncryptionService(domain)).decrypt(password);
                           //STORE & Return
                userCredentials.put("username", decryptUser);
                userCredentials.put("password", decryptPass);

                return userCredentials;

            } catch (Exception ex) {
                System.out.print(ex);


            }
       
        return userCredentials;

    }

/**
     *  reads the boot properties from the domaindir
     */
    public String[] readBootProperties(String domainDir) {
        String str = "";
        File file =
            new File(domainDir + "/servers/AdminServer/security/boot.properties");
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(file);

            int content;

            while ((content = fis.read()) != -1) {
                // convert to char and display it
                str += (char)content;
                //System.out.print((char) content);
            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return str.split("\n");
    }
Depending on your domain installation you might need to change a few strings to get the
readBootProperties(String domainDir)
Reading the correct files