Hi there,
A few weeks ago I created the following post: SAP Work Manager 6.2.0: How To Add Pictures to a Local Notification (using BDS)
In this blog, I will describe how to implement the closely related functionality that allows the user to have offline access to all the BDS notification pictures (or documents) after executing the transmit action.
Be careful with this because it can cause huge performance issues since we will retrieve the content of all the BDS documents linked to the user notifications. In my scenario, most of the documents, manuals and other work order related material are assigned via DMS and retrieved in a different way out of Agentry. Only the notification pictures are BDS attachments, therefore fetching the content won't cause too much trouble.
The Problem:
Work Manager 6.2.1 introduces a new functionality to download attachments via synchronous call instead of the push request fetch that is causing a lot of problems to developers implementing the solution. If you are running Work Manager 6.2.0 there is a separate note to implement this: http://service.sap.com/sap/support/notes/2142473
But even with this enabled, the documents are only retrieved under user request, so if there is no connectivity it won't be possible to fetch the attachment content. In my scenario, field technicians are working mostly offline and they need to have all the attachments available once the transmit finishes and they leave the facilities with internet access.
Development Overview:
Agentry UI changes:
The Agentry changes are minimum. Only a new fetch executed every transmit has been created with its corresponding steplet.
Java changes:
There are multiple Java changes divided in 2 separate concepts. The 1st one is to fetch and store the notification document links with the binary content into the DocumentLinks component manager during the notification fetch execution. The 2nd one is the transmit steplet executed during the newly created Agentry Fetch that will retrieve the previously stored Document Links to populate the Agentry collection.
1. Store Document Links with content to the component manager. Classes Notification and WorkorderNotification have to be extended
public static final String ATTACHMENT_SYNCH_ENABLE_SECTION = "APPLICATION_CONFIG";
public static final String ATTACHMENT_SYNCH_ENABLE = "ZAttachment.SynchOnTransmit";
public static boolean isFetchOnTransmitEnabled(User user) throws AgentryException{
return user.getPropertyValue(ATTACHMENT_SYNCH_ENABLE_SECTION, ATTACHMENT_SYNCH_ENABLE).equalsIgnoreCase("Y");
}
public static void getDocumentLinkContentToComponentManager(DocumentLink dl, User user){
Logger log = new Logger(user, "getDocumentLinkContentToComponentManager");
try{
DocumentLinkComponentManager documentLinkCompManager = (DocumentLinkComponentManager)user.getComponentManager(DocumentLinkComponentManager.class.getCanonicalName());
if(dl.isBDS() && dl.getFileMimeType().matches("image/(.*)")){
ArrayList<? extends SAPObject> recs = null;
dl.setDocID(dl.getID());
String agentryLastUpdate = user.eval("<<lastUpdate format=\"%m/%d/%Y %H:%M:%S\">>");
GregorianCalendar lastUpdate = ConversionUtility.getTimeStampFromString(agentryLastUpdate, ConversionUtility.TIMESTAMPFORMAT);
//Call the BAPI to read the binary data for the document
BDSDocumentSynchFetchBAPI bapi = (BDSDocumentSynchFetchBAPI) BAPIFactory.create("BDSDocumentSynchFetchBAPI",
new Class<?>[] {User.class, GregorianCalendar.class, SAPObject.class},
new Object[] {user, lastUpdate, dl});
bapi.run(dl);
recs = bapi.processResults();
if(recs.size() > 0){
//Store the retrieved document to the component manager,
//DocumentLinksFetchOnTransmitSteplet will access to the data afterwards
//documentLinkCompManager.addObject(recs.get(0));
Object val = recs.get(0);
if (val instanceof DocumentLink){
DocumentLink documentWithContent = (DocumentLink)val;
documentLinkCompManager.addObject(documentWithContent);
log.info("::Document ID = " + documentWithContent.getDocID());
}
}
}
}catch(Exception e){
log = new Logger(
Server.getSAPServer(),
"com.syclo.sap.workmanager.customer.DocumentLinkUtils" +
"::getDocumentLinkContentToComponentManager(dl,user)::Thread " +
Thread.currentThread().getId() + "::");
log.error(e.getMessage());
e.printStackTrace();
}
}
@Override
public void addDocumentArrayList(ArrayList<DocumentLink> linkedDocuments){
Logger log = new Logger(_user, "addDocumentArrayList");
try{
if(linkedDocuments.size() > 0 && DocumentLinkUtils.isFetchOnTransmitEnabled(_user)){
Iterator<DocumentLink> it = linkedDocuments.iterator();
while(it.hasNext()){
DocumentLink dl = it.next();
DocumentLinkUtils.getDocumentLinkContentToComponentManager(dl, _user);
}
}
}catch(Exception e){
log = new Logger(
Server.getSAPServer(),
"com.syclo.sap.workmanager.customer.object.Notification" +
"::addDocumentArrayList(linkedDocuments)::Thread " +
Thread.currentThread().getId() + "::");
log.error(e.getMessage());
e.printStackTrace();
}
super.addDocumentArrayList(linkedDocuments);
}
@Override
public void init() throws Exception {
//Only call super init() if _documentLink.ID is initial
if(_documentLink.getDocID().equalsIgnoreCase("")){
super.init(); //Gets the ID from the Agentry fetch
}
}
2. Steplet executed by the newly created Agentry fetch to populate document links into the Agentry collection.
@Override
public boolean execute() throws AgentryException {
try {
ZDocumentLinksFetchOnTransmitStepHandler handler = (ZDocumentLinksFetchOnTransmitStepHandler) StepHandlerFactory.create(
StepHandlerFactory.getClassName("ZDocumentLinksFetchOnTransmitStepHandler"),
new Class[] { com.syclo.sap.User.class },
new Object[] { _user });
ArrayList<SAPObject> recs = handler.run();
int sz = recs.size();
if (sz > 0) {
_returnData = createSAPObjectArray(getSAPObject(), recs);
}
return true;
}
catch (Throwable e)
{
throwExceptionToClient(e);
return false;
}
}
public class ZDocumentLinksFetchOnTransmitStepHandler extends StepHandler {
public static final String COMPONENT_MANAGER_CLASS_NAME = DocumentLinkComponentManager.class.getCanonicalName();
protected DocumentLinkComponentManager _compManager;
public ZDocumentLinksFetchOnTransmitStepHandler(User user) throws Exception {
super(user);
_compManager = (DocumentLinkComponentManager)_user.getComponentManager(COMPONENT_MANAGER_CLASS_NAME);
}
/**
* Get the list of Document Links for the user by reading from the component manager
* table associated with the user object. This method does not call any BAPI. This method
* assumes that the user's hashtable has been populated previously from Notification and/or
* Work Order fetch
*
* @return list of DocumentLink objects populated in fetch
* @throws AgentryException
*/
public ArrayList<SAPObject> run() throws AgentryException {
String methodLabel = "run";
Logger log = new Logger(_user, methodLabel);
ArrayList<SAPObject> recs = new ArrayList<SAPObject>();
if (DocumentLinkUtils.isFetchOnTransmitEnabled(_user)) {
_user.inFetch(true);
Hashtable<String, DocumentLink> headers = _compManager.getObjects();
Enumeration<?> e = headers.elements();
while (e.hasMoreElements()) {
Object val = e.nextElement();
if (val instanceof DocumentLink) {
DocumentLink dl = (DocumentLink)val;
recs.add(dl);
log.info("::Document ID = " + dl.getDocID());
}
}
}
log.info("::end");
return recs;
}
}
Configuration Portal Adjustments:
Finally, some adjustments have to be done in the configuration portal for the newly created classes and parameters
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
11 | |
9 | |
7 | |
6 | |
4 | |
4 | |
3 | |
3 | |
3 | |
3 |