Category Archives: IBM Content Navigator

Customize the progress message of your service

By default, in IBM Content Navigator, the progress message when you are invoking a plug-in’s service is always Working… However, you may want something more meaningful. Give a progressMessage attribute to the plugin parameters doesn’t work because the Request class overwrite it anyway. You have to define one of the following attribute in the messages list.

  • progress_message_repositoryType_serviceName
  • progress_message_serviceName

Here is an example:

var serviceParams = {};
serviceParams[Constants.PARAM_REPOSITORY] = repository.id;
serviceParams[Constants.PARAM_SERVER_TYPE] = repository.type;
serviceParams[Constants.PARAM_FOLDER_ID] = items[0].id;
ecm.messages.progress_message_PrimeReleaseService = "Priming " + items[0].name + "...";

Request.invokePluginService("GenericActionsPlugin", "PrimeReleaseService", {
    requestCompleteCallback: lang.hitch(this, function (response) {
        this.displayResults(response);
    }),
    requestParams : serviceParams
});

How works the FileTracker in ICN

Since I spent some time working with the File Tracker, I thought I would write how it really works. This is useful to know:

  • what can be manually done with the files without preventing the File Tracker to work
  • what can be done when downloading file via ICN, especially sub-folders speaking

Principle

The File Tracker applet will use the desktop’s configuration to know what is the File Tracker directory. That can be an environment variable, user home directory, user document directory, or a hard defined folder. Then it will download all documents in this folder, and will be able to find them back for the check in. That way, the user does not have to give the file himself when checking in.

How the FileTracker store and retrieve files

Continue reading

Callback not working in the FileTracker functions

Status: fixed in 2.0.3.3

You might have noticed that when using the ecm/model/FileTracker class in IBM Content Navigator, the callback is never called.

For instance if you are using the following code:

FileTracker.downloadAndTrackFiles(documentInfoObj, function (response) {
    console.log("Never invoked");
});

the callback is never called. This is because there is a defect in the FileTracker processMessage function, it does not look correctly for the callback because of a = missing in the condition:

var callbackResponse;
if (response.responses && response.responses.length > 0) {
	var callbackResponse;
	for ( var i = 0; i < response.responses.length; i++) {
		if (response.responses[i].errorCode = this.SERVER_RESPONSE_CALLBACK) {
			callbackResponse = response.responses[i];
			break;
		}
	}
} else if (response.errorCode == this.SERVER_RESPONSE_CALLBACK) {
	callbackResponse = response;
}

This is fixed in Fix Pack 3 though (2.0.3.3), so you can either upgrade or use a plugin to do an aspect around and replace the function by the correct one, which is:

processMessage: function(json, showSuccessMessage) {
	var methodName = "processMessage";
	this.logEntry(methodName);

	var response = dojojson.fromJson(json);
	if (response.hasError) {
		var errorPrefix = "", inserts = [];
		var showError = true;
		if (response.errorCode == 7) {//ERROR_OPEN_FAILED
			errorPrefix = "runtime_file_tracking_file_not_found_error";
		} else if (response.errorCode == 3) {
			errorPrefix = "runtime_file_tracking_ioexception_error";
		} else if (response.errorCode == this.ERROR_NOT_TRACKED) {
			showError = false;
		} else if (response.errorCode == this.ERROR_OPEN_FAILED) {
			showError = true;
			errorPrefix = "runtime_file_tracking_open_error";

		} else if (response.errorCode == this.ERROR_SAVE_FILE_FAILED) {
			showError = true;
			errorPrefix = "runtime_file_tracking_save_file_error";

		} else if (response.errorCode == this.ERROR_SAVE_FILE_FAILED_AND_OPEN_FIALED) {
			showError = true;
			errorPrefix = "runtime_file_tracking_save_file_after_checkout_error";

		} else if (response.errorCode == this.ERROR_ENVIRONMENT_VARIABLE_PATH_NOT_FOUND) {
			showError = true;
			errorPrefix = "runtime_file_tracking_ev_file_path_not_found_error";

		} else if (response.errorCode == this.ERROR_OPEN_CONNECTION) {
			showError = true;
			errorPrefix = "runtime_file_tracking_ioexception_error";

		} else if (response.errorCode == this.ERROR_FOLDER_NOT_FOUND) {
			showError = true;
			errorPrefix = "runtime_file_tracking_exact_file_path_not_found_error";

		} else if (response.errorCode == this.ERROR_EXACT_PATH_NOT_FOUND) {
			showError = true;
			errorPrefix = "runtime_file_tracking_exact_file_path_not_found_error";

		} else if (response.errorCode == this.ERROR_CANNOT_CREATE_TRACKING) {
			showError = false;
			errorPrefix = "runtime_file_tracking_exact_file_path_not_found_error";

		} else if (response.errorCode == this.ERROR_DELETE_FILE_FAILED) {
			showError = true;
			errorPrefix = "runtime_file_tracking_cannot_delete_file_error";

		} else {
			showError = true;
			errorPrefix = "runtime_file_tracking_generic_error";
		}

		if (showError) {
			if (response.responses && response.responses[0].value) {
				inserts.push(response.responses[0].value);
			} else if (response.value) {
				inserts.push(response.value);
			}
			Desktop.addMessage(Message.createErrorMessage(errorPrefix, inserts, false));
		}

	} else {
		var successMessage = "";
		if (response.responses) {

			if (response.responses.length == 1 && ((response.responses[0].errorCode == this.ERROR_DELETE_FILE_FAILED || response.responses[0].errorCode == this.FOUND_TRACKED_RECORD_BY_FILE_PATH) || (response.responses[0].errorCode == this.FOUND_TRACKED_RECORD_BY_SCANNING) || (response.responses[0].errorCode == this.SUCCESSFULLY_TRACKED_FILE_USING_ADS))) {

				successMessage = string.substitute(ecm.messages.file_tracking_successfully_downloaded_document, [
					response.responses[0].originalDocumentName,
					response.responses[0].value
				]);
			} else if (response.responses.length > 1 && ((response.responses[0].errorCode == this.FOUND_TRACKED_RECORD_BY_FILE_PATH) || (response.responses[0].errorCode == this.FOUND_TRACKED_RECORD_BY_SCANNING) || (response.responses[0].errorCode == this.SUCCESSFULLY_TRACKED_FILE_USING_UD) || (response.responses[0].errorCode == this.SUCCESSFULLY_TRACKED_FILE_USING_ADS))) {

				var count = response.responses.length;
				var documentsDownloaded = [];
				for ( var i = 0; i < count; i++) {
					documentsDownloaded.push(response.responses[i].originalDocumentName);
				}
				successMessage = string.substitute(ecm.messages.file_tracking_successfully_downloaded_document, [
					documentsDownloaded.join(",")
				]);

			}
		}

		if (successMessage && successMessage.length > 0) {
			Desktop.addMessage(new Message({
				number: 0,
				level: 0,
				text: successMessage
			}));
		}

		var callbackResponse;
		if (response.responses && response.responses.length > 0) {
			var callbackResponse;
			for ( var i = 0; i < response.responses.length; i++) {
				if (response.responses[i].errorCode == this.SERVER_RESPONSE_CALLBACK) {
					callbackResponse = response.responses[i];
					break;
				}
			}
		} else if (response.errorCode == this.SERVER_RESPONSE_CALLBACK) {
			callbackResponse = response;
		}
		if (callbackResponse && callbackResponse.value) {
			var lookupId = callbackResponse.value.callbackId;
			if (lookupId && this.callbackMap[lookupId]) {
				var callbackFunc = this.callbackMap[lookupId];
				if (callbackFunc) {
					callbackFunc(callbackResponse.value.response);
				}
			}
		}

	}

	this.logExit(methodName);
	return response;
	//MessageFactory.createErrorMessage = function(messagePrefix, inserts, backgroundRequest);

},

Feature is not implemented: PreparedStatement.setBinaryStream

Today I faced this new issue I’ve never got before. It happened when I was trying to set Entry Template on a folder in ICN, which is weird because I did that plenty of times in the past.

Perhaps another app I installed changed a configuration in WebSphere.

Here is the symptoms when I was updating the entry templates on the folder:

ICN_JDBC4_error

Message as text:

Contact your system administrator with the following information: An unexpected exception occurred. The unexpected exception is chained to this exception. Message was: RemoteException occurred in server thread; nested exception is: java.rmi.RemoteException: ; nested exception is: com.filenet.api.exception.EngineRuntimeException: FNRCC0036E: CONTENT_DCA_FAILED_INSERT: The content element could not be inserted.

And in the SystemOut.log from WebSphere:

000000e2 .ibm.ejs.container.LocalExceptionMappingStrategy 3    NON_APPLICATION_EXCEPTION_METHOD_ON_BEAN_CNTR0020E                   
                                 com.filenet.api.exception.EngineRuntimeException: FNRCC0036E: CONTENT_DCA_FAILED_INSERT: The content element could not be inserted.                                                              
        at com.filenet.engine.content.DatabaseContentArea.copyElementToInbound(DatabaseContentArea.java:2034)    
        at com.filenet.engine.content.ContentStreamUploader.doUpload(ContentStreamUploader.java:196)             
        at com.filenet.engine.content.PutContentHandler.putContent(PutContentHandler.java:203)                   
        at com.filenet.engine.jca.impl.RequestBrokerImpl.putContent(RequestBrokerImpl.java:448)                  
        at com.filenet.engine.jca.impl.RequestBrokerImpl.putContent(RequestBrokerImpl.java:356)                  
        at com.filenet.engine.ejb.EngineContentCoreBean._putContent(EngineContentCoreBean.java:82)               
        at com.filenet.engine.ejb.EngineContentCoreBean.putContent(EngineContentCoreBean.java:57)                
        at com.filenet.engine.ejb.EJSLocalStatelessEngineContentCore_dd5e7ec6.putContent(Unknown Source)         
        at com.filenet.engine.ejb.EngineContentBean.putContent(EngineContentBean.java:192)                       
        at com.filenet.apiimpl.transport.ejbstubs.EJSRemoteStatelessEngineContent_a66a23a6.putContent(Unknown Source)                                                                                                             
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)                                           
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:88)                         
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)                 
        at java.lang.reflect.Method.invoke(Method.java:613)                                                      
        at com.ibm.rmi.util.ProxyUtil$4.run(ProxyUtil.java:609)                                                  
        at java.security.AccessController.doPrivileged(AccessController.java:280)                                
        at com.ibm.rmi.util.ProxyUtil.invokeWithClassLoaders(ProxyUtil.java:606)                                 
        at com.ibm.CORBA.iiop.ClientDelegate.invoke(ClientDelegate.java:1177)                                    
        at $Proxy140.putContent(Unknown Source)                                                                  
        at com.filenet.apiimpl.transport.ejbstubs._EngineContent_Stub.putContent(Unknown Source)                 
        at com.filenet.apiimpl.transport.ejb.ContentEJB.putContent(ContentEJB.java:475)                          
        at com.filenet.apiimpl.transport.ejb.ContentPush$EJBImpl.putContent(ContentPush.java:892)                
        at com.filenet.apiimpl.transport.ejb.ContentPush$EJBImpl.run(ContentPush.java:749)                       
        at java.security.AccessController.doPrivileged(AccessController.java:314)                                
        at javax.security.auth.Subject.doAs(Subject.java:572)                                                    
        at com.ibm.websphere.security.auth.WSSubject.doAs(WSSubject.java:195)                                    
        at com.ibm.websphere.security.auth.WSSubject.doAs(WSSubject.java:152)                                    
        at sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source)                                          
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)                 
        at java.lang.reflect.Method.invoke(Method.java:613)                                                      
        at com.filenet.apiimpl.util.J2EEUtilWS.doAs(J2EEUtilWS.java:220)                                         
        at com.filenet.apiimpl.transport.ejb.ContentPush$EJBImpl.uploadContent(ContentPush.java:555)             
        at com.filenet.apiimpl.transport.ejb.ContentPush.uploadContent(ContentPush.java:312)                     
        at com.filenet.apiimpl.transport.ejb.ContentPush.singleThreadUpload(ContentPush.java:289)                
        at com.filenet.apiimpl.transport.ejb.ContentPush.uploadContent(ContentPush.java:152)                     
        at com.filenet.apiimpl.transport.ejb.EJBSession.executeChanges(EJBSession.java:371)                      
        at com.filenet.apiimpl.util.SessionHandle.executeChanges(SessionHandle.java:112)                         
        at com.filenet.apiimpl.core.Session.callExecuteChanges(Session.java:144)                                 
        at com.filenet.apiimpl.core.Session.executeChanges(Session.java:527)                                     
        at com.filenet.apiimpl.core.Session.executeChange(Session.java:830)                                      
        at com.filenet.apiimpl.core.IndependentlyPersistableObjectImpl.save(IndependentlyPersistableObjectImpl.java:85)                                                                                                           
        at com.filenet.apiimpl.core.IndependentlyPersistableObjectImpl.save(IndependentlyPersistableObjectImpl.java:76)                                                                                                           
        at com.ibm.ecm.util.p8.P8FolderTemplates.associateTemplatesWithFolder(P8FolderTemplates.java:120)        
        at com.ibm.ecm.struts.actions.p8.P8SaveEntryTemplateFolderAssociations.executeAction(P8SaveEntryTemplateFolderAssociations.java:33)                                                                                       
        at com.ibm.ecm.struts.actions.p8.P8BaseAction.executeBaseAction(P8BaseAction.java:183)                   
        at com.ibm.ecm.struts.actions.BaseAction.execute(BaseAction.java:211)                                    
        at com.ibm.ecm.jaxrs.Actions.loadAndExecuteAction(Actions.java:241)                                      
        at com.ibm.ecm.jaxrs.Actions.handleAction(Actions.java:83)                                               
        at com.ibm.ecm.jaxrs.Actions.handlePostRepositoryActions(Actions.java:183)                               
        at sun.reflect.GeneratedMethodAccessor123.invoke(Unknown Source)                                         
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)                 
        at java.lang.reflect.Method.invoke(Method.java:613)                                                      
        at org.apache.wink.server.internal.handlers.InvokeMethodHandler.handleRequest(InvokeMethodHandler.java:63)                                                                                                                
        at org.apache.wink.server.handlers.AbstractHandler.handleRequest(AbstractHandler.java:33)                
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.internal.handlers.CreateInvocationParametersHandler.handleRequest(CreateInvocationParametersHandler.java:54)                                                                                    
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.handlers.AbstractHandler.handleRequest(AbstractHandler.java:34)                
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.internal.handlers.FindResourceMethodHandler.handleSubResourceMethod(FindResourceMethodHandler.java:183)                                                                                         
        at org.apache.wink.server.internal.handlers.FindResourceMethodHandler.handleRequest(FindResourceMethodHandler.java:110)                                                                                                   
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.internal.handlers.FindRootResourceHandler.handleRequest(FindRootResourceHandler.java:95)                                                                                                        
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.internal.handlers.HeadMethodHandler.handleRequest(HeadMethodHandler.java:53)   
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.internal.handlers.OptionsMethodWADLHandler.handleRequest(OptionsMethodWADLHandler.java:51)                                                                                                      
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.internal.handlers.SearchResultHandler.handleRequest(SearchResultHandler.java:33)                                                                                                                
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.internal.log.ResourceInvocation.handleRequest(ResourceInvocation.java:92)      
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.internal.log.Requests.handleRequest(Requests.java:76)                          
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:26)             
        at org.apache.wink.server.handlers.RequestHandlersChain.handle(RequestHandlersChain.java:22)             
        at org.apache.wink.server.handlers.AbstractHandlersChain.doChain(AbstractHandlersChain.java:75)          
        at org.apache.wink.server.handlers.AbstractHandlersChain.run(AbstractHandlersChain.java:60)              
        at org.apache.wink.server.internal.RequestProcessor.handleRequestWithoutFaultBarrier(RequestProcessor.java:207)                                                                                                           
        at org.apache.wink.server.internal.RequestProcessor.handleRequest(RequestProcessor.java:154)             
        at org.apache.wink.server.internal.servlet.RestServlet.service(RestServlet.java:124)                     
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)                                          
        at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1214)                      
        at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:774)                 
        at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:456)                 
        at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)         
        at com.ibm.ws.webcontainer.filter.WebAppFilterChain.invokeTarget(WebAppFilterChain.java:125)             
        at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:77)                  
        at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:926)             
        at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1023)       
        at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:87)        
        at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:895)                             
        at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1662)                        
        at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:195)                           
        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458)   
        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:522)       
        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:311)         
        at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:87)        
        at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)                                                                                                              
        at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)                     
        at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)                
        at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)                                          
        at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)                                       
        at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)                         
        at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)                                          
        at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1783)                                           
Caused by: com.filenet.api.exception.EngineRuntimeException: FNRCD0009E: DB_ERROR: The database access failed with the following error: ErrorCode 0, Message 'DSRA1300E: Feature is not implemented: PreparedStatement.setBinaryStream' ObjectStore: "TARGETOS"                                                                                    
        at com.filenet.engine.dbpersist.DBDB2Context.throwEngineException(DBDB2Context.java:730)                 
        at com.filenet.engine.dbpersist.DBContext.throwEngineException(DBContext.java:1277)                      
        at com.filenet.engine.dbpersist.DBStatementBase.setBinding(DBStatementBase.java:640)                     
        at com.filenet.engine.dbpersist.DBStatementBase.buildSingleExecution(DBStatementBase.java:526)           
        at com.filenet.engine.dbpersist.DBStatementBase.execute(DBStatementBase.java:271)                        
        at com.filenet.engine.content.DatabaseContentArea.copyElementToInbound(DatabaseContentArea.java:2027)    
        ... 122 more                                                                                             
Caused by: java.sql.SQLFeatureNotSupportedException: DSRA1300E: Feature is not implemented: PreparedStatement.setBinaryStream                                                                                                     
        at com.ibm.ws.rsadapter.AdapterUtil.notSupportedX(AdapterUtil.java:1460)                                 
        at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.setBinaryStream(WSJdbcPreparedStatement.java:1424)  
        at com.filenet.engine.dbpersist.DBStatementBase.setBinding(DBStatementBase.java:624)                     
        ... 125 more                                                                                             
Caused by: java.lang.AbstractMethodError: java/sql/PreparedStatement.setBinaryStream(ILjava/io/InputStream;)V    
        at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.setBinaryStream(WSJdbcPreparedStatement.java:1408)  
        ... 126 more   

It seems that my DataSources are not using JDBC 4 anymore but 3 instead (strange ???). To fix this, go to your JDBC DataProvider in WebSphere Resources > JDBC > JDBC Data Providers and edit the providers :

  • IBM Content Navigator JDBC provider for DB2
  • JDBC provider for DB2
  • JDBC provider for DB2 (XA)

to modify in the Class Path:

${DB2UNIVERSAL_JDBC_DRIVER_PATH}/db2jcc.jar

to

${DB2UNIVERSAL_JDBC_DRIVER_PATH}/db2jcc4.jar

ICN_JDBC4_fix

 

And restart you WebSphere server. That should fix the issue.

Push updates from an ICN service to your client with CometD

One feature I really miss in ICN right now is a 2 ways communication channel between service and client. At this moment, you call your service and then it returns something when the execute method is done. That creates an issue, because users have no patience… More than one minute on the same loading spinner and you can be sure most of them will refresh the page thinking ICN crashed. That won’t stop your service, but if this one is not done by the time the user comes back, he will run the service again…

So here is a way to push information from the server to the client.

Principle

I used CometD to implement that because ICN is already shipped with some CometD client libraries (actually not all of them, discussed below)). The reason for that is ICN uses CometD for the Sync and Share feature. That way we don’t need to add any library to the client. About the server, the PluginService class is not a servlet or a web service, it is actually called by a Struts action so forget about asynchronous servlet, websocket and so on since we are not master of our servlet. On the other hand, we can’t change the navigator application either (well we could and redeploy but we want to be update proof), so we can’t add support for any “push” framework and ICN doesn’t have that natively. That’s why I’ve decided to use another light web application to achieve that. Here is the schema to help you understand how it works.

ICN_CometD_push
Continue reading

Understand messaging and logging in ICN

In this post, I’ll explain how messaging and logging work in ICN and how to use them to give meaningful information to users and developers.

First, what’s the difference between messaging and logging? Messaging means showing information to the user. These information are meaningful to them and have to be shown to all users.

Logging means persisting information to track the application execution. These information are not supposed to be shown to users. They help tracking defects more quickly.
Continue reading

Transfer a file to your service

Some business logic can require to send a file from the client workstation to the server. Usually to improve performance by doing a server work instead of a client one, sometimes because it’s more convenient for the user or for the developer. I had to transfer a zip to do a zip-add after I noticed that deflating on the client and adding file one by one was to slow for our needs, although it worked fine.

Client side

On the client, we won’t use the function Request.invokePluginService as we usually do when invoking services. Instead, we are going to use Request.postFormToPluginService(pluginName, pluginServiceName, form, pluginParams), which allow posting data to our service. However the syntax differs, here we won’t pass our params in the requestParams attribute of the pluginParams argument, this time they all go in the form, which is a W3C FormData object, along with our W3C File. Here is the example.

var fd = new FormData();
fd.append('file', zipArchive);
fd.append(Constants.PARAM_FOLDER_ID, this.parentFolder.id);
fd.append(Constants.PARAM_REPOSITORY, this.parentFolder.repository.id);
fd.append(Constants.PARAM_SERVER_TYPE, this.parentFolder.repository.type);

var pluginParams = {
    requestCompleteCallback: lang.hitch(this, function (response) {
        this.parentFolder.refresh();
    })
};

Request.postFormToPluginService("GenericActionsPlugin", "AddZipService", fd, pluginParams);

This is all it takes on the client.

Server side

Now let’s see how to fetch this file and use it in our service.

ICN is still using Struts. That means we will use the FormFile interface to get our file (actually the stream). The FormFile is added as attribute of the request by the PluginAction class in charge to call your Plugin class so you can retrieve it with:

FileUploadActionForm uploadForm = (FileUploadActionForm) request.getAttribute(FileUploadActionForm.class.getName());
if (upload != null) {
    FormFile ff = (FormFile) uploadForm.getMultipartRequestHandler().getFileElements().get("file");
}

In order for this to work, you will have to add to your classpath the ICN classes. You can find them by deflating the ear file or going to your application server in the installed app, usually there will be the exploded ear there too. That could be more convenient to zip all WEB-INF/classes in a jar and add that to your classpath.

However, the other parameters are still retrieved with request.getParameter().

Then you can use the stream. If you need a file, even if in the ICN implementation FormFile, the file is actually stored in a WAS temp directory, this is not possible to get it so you’ll have to copy the stream in a temp file and use this file instead.

Here is the server side example corresponding to the client.

String repositoryId = (String) request.getParameter(Constants.PARAM_REPOSITORY);
String parentFolderIcnId = (String) request.getParameter(Constants.PARAM_FOLDER_ID);
String parentFolderId = P8Helper.getP8ID(parentFolderIcnId);

ObjectStore os = callbacks.getP8ObjectStore(repositoryId);

FileUploadActionForm uploadForm = (FileUploadActionForm) request.getAttribute(FileUploadActionForm.class.getName());
if (uploadForm != null) {
    FormFile ff = (FormFile) uploadForm.getMultipartRequestHandler().getFileElements().get("file");

    if (ff != null) {
        InputStream is = ff.getInputStream();
        // Do something with the stream
    }
}

Drag and Drop a folder in IBM Content Navigator

Nowadays, everyone seems to think dropping a folder is somehow optional. They all have given up on the File API “Directories and System” (except Google which at least implemented it). I have to admit, I clearly don’t understand because in the ECM world, that just a must-have feature…

Anyway, since this is something our users are expecting, especially since there are used to it with the Workplace XT (via the applet), we had to find a workaround. Actually we found two which are quite complementary. One is using the Chrome Directories and System API, which really allows a true folder drop, but way better than Workplace XT since it’s applet free and therefore mobile supported. The other is supported by all browsers and requires the user to only zip the folder and drop the zip. It’ is only 1 second extra work for the user instead of the hours it would have to spend to create all the folder hierarchy manually and upload files folder by folder. This seems like a good alternative and again, it is supported by every brother.

Let’s present these two workarounds quickly. I won’t explain the whole implementation since it might get quite complex but instead, I will explain how to address the problem.
Continue reading

File Tracker download directory regression

Using Workplace XT, we were able to keep the folder hierarchy of a Document within the Object Store when downloading it with the File Tracker applet. That means, if your document’s path was /Folder/SubFolder/Document.xml, and your FileTracker folder on the client was C:\FileNet\Work, then you would get your document downloaded as C:\FileNet\Work\ObjectStoreName\Folder\SubFolder\Document.xml.

That’s no longer true with ICN. Everything goes into your download folder, C:\FileNet\Work in the previous example, without creating any sub-directories. This is especially an issue if you download a lot of document and want to edit them, this folder becomes a mess, and if a lot of documents are called the same in your Object Store, then you will have conflicts.

Officially, this is because this functionality is now covered by the Sync and Share feature, which uses a client agent on Windows platform, and is embedded in mobile applications. However this does not cover Unix platforms, and does not allow using Entry Templates, which can be a requirement for your platform. That’s why we will see how to make it work in ICN anyway.

How to fix that

Continue reading