Skip to Content

When developing custom java-proxy often enough there is a situation when you want to log actions/steps during java-proxy work. Usually methods of com.sap.tc.logging.Location class can be used for that purpose. Those allow you to log events which you can see in Log Viewer(view / developer trace, fig.1).

Fig.1 Example of developer trace logs @ Log Viewer.

Using that Log Viewer developer trace approach has its own downsides such as if your java-proxy works under relatively high load finding log entries for certain message could be challenging because Log Viewer search tool listing capabilities are limited with page scroll option.

Besides, message monitoring becoming separated on two stages: first you have to check audit log in Message Monitor, and then or even at the same time – try to find (your java-proxy made) records for that message in Log Viewer. When you use couple of integration scenarios, this is not a significant problem. However, when there are many such scenarios (for example, Technosoft develops and supports hundreds of complex integration scenarios), a problem arises how effectively monitors scenarios used java-proxy.

Obviously there is a question: is that possible to create log entries during java-proxy execution (work) not in Log Viewer but in Message Monitor? Seems convenient to be able to see all log entries at the same page (default and custom created) as well as being able to monitor messages right in Message Monitor.

By default SAP provides tools necessary to create custom audit log entries, when developing custom communication channel modules. In this case you can use related classes of standard XPI Adapter Library included in SAP NWDS. But what if we want to use this tool to create log entries during java-proxy execution? To be able to do that we need to create AuditAccess object which have methods that can be used to create audit log entries. You can create this object using following code:

AuditAccess auditAccess = PublicAPIAccessFactory.getPublicAPIAccess().getAuditAccess();

If we’ll just create this object and deploy java-proxy to a server, during test message processing we’ll be able to see following error in Log Viewer (fig.2).

Fig.2 Log Viewer error.

Looks like this way won’t work.

While experimenting, I’ve been able to find at least one way to create log entries in Audit Log from java-proxy. By using java reflection mechanism I was able to get all classes and methods needed to create audit log entries. I’ve created separate java class contains addLogEntry() method which will allow to log information needed to monitor/analyze java-proxy message processing in Audit Log. Following class code can be used:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.sap.engine.interfaces.messaging.api.MessageDirection;
import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus;

public class MessageMonitor {
	private Method mtdAddAuditLogEntry;
	private Object objAuditAccess;
	private Class clsMessageKey;
	private Class clsLogStatus;
	private Object objMessageKey;
	
	public MessageMonitor(String msgId, MessageDirection msgDirection) throws NamingException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
		Context context = new InitialContext();
		
		Class clsAPIPublick = context.lookup("com.sap.engine.interfaces.messaging.api.public").getClass();
		Object objAPIPublick = clsAPIPublick.newInstance();
		Method mtdGetAuditAccess = clsAPIPublick.getDeclaredMethod("getAuditAccess");
		
		objAuditAccess = mtdGetAuditAccess.invoke(objAPIPublick);
		Class clsAuditAccess = objAuditAccess.getClass();
	
		for (Method mtd : clsAuditAccess.getMethods()) {
			for (Class cls : mtd.getParameterTypes()) {
				if (cls.getCanonicalName().equals("com.sap.engine.interfaces.messaging.api.MessageKey")) {
					clsMessageKey = cls;
				} else if (cls.getCanonicalName().equals("com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus")) {
					clsLogStatus = cls;
				}
			}
			if (clsMessageKey != null && clsAuditAccess != null) break;
		}
		
		mtdAddAuditLogEntry = clsAuditAccess.getMethod("addAuditLogEntry", new Class[]{clsMessageKey, clsLogStatus, String.class});
		
		Class clsMessageDirection = null;
		outer: for (Constructor cnstr : clsMessageKey.getConstructors()) {
			for (Class cls : cnstr.getParameterTypes()) {
				if (cls.getCanonicalName().equals("com.sap.engine.interfaces.messaging.api.MessageDirection")) {
					clsMessageDirection = cls;
					break outer;
				}
			}
		}
		
		Constructor cnstrMessageDirection = clsMessageKey.getConstructor(new Class[]{String.class, clsMessageDirection});
		Field fldMessageDirection = clsMessageDirection.getField(msgDirection.toString());
		objMessageKey = cnstrMessageDirection.newInstance(new Object[]{new String(msgId), fldMessageDirection.get(clsMessageDirection)});
	}
	
	public void addLogEntry(AuditLogStatus logStatus, String logMsg) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Field fldLogStatus;
		if (logStatus.toString().equals("S")) {
			fldLogStatus = clsLogStatus.getField("SUCCESS");
		} else if (logStatus.toString().equals("W")) {
			fldLogStatus = clsLogStatus.getField("WARNING");
		} else {
			fldLogStatus = clsLogStatus.getField("ERROR");
		}
		
		mtdAddAuditLogEntry.invoke(objAuditAccess, new Object[]{objMessageKey, fldLogStatus.get(clsLogStatus), new String(logMsg)});
	}
}

To make this code actually work we need to perform several following steps.

Create an instance of this class using constructor MessageMonitor(String msgId, MessageDirection msgDirection). First parameter – message id, second – message direction(inbound/outbound).

To get message id in java-proxy we are going to use following classes:

          com.sap.engine.services.webservices.espbase.server.additions.xi.ProviderXIMessageContext located in standard SAP NWDS: SAP Java EE 5 Libraries (tc~je~webservices~lib.jar).

          com.sap.guid.IGUID can be found in sap.com~tc~bl~guidgenerator~impl.jar. You can also find it using file path: /usr/sap/<SID>/<instance>/j2ee/cluster/bin/core_lib/

After adding those classes to your project following code can be used to get message id during java-proxy work:

ProviderXIMessageContext context = ProviderXIMessageContext.getInstance()
String msgId = context.getRequestMessageID().toString();

To get message direction we can use MessageDirection class static fields: for inbound java-proxy – MessageDirection.INBOUND, for outbound java-proxy – MessageDirection.OUTBOUNB. MessageDirection class is located in standard SAP NWDS – XPI Adapter Libraries (com.sap.aii.af.ifc.filter.jar).

When instance of MessageMonitor class is created there is going to be available a method using which we can create custom log entries in Audit Log – addLogEntry(AuditLogStatus logStatus, String logMsg). First parameter – log entry type(Success, Warning or Error), it can be done by using static fields of AuditLogStatus class such as: AuditLogStatus.SUCCESS, AuditLogStatus.WARNING or AuditLogStatus.ERROR.

AuditLogStatus class also can be found in standard SAP NWDS – XPI Adapter Libraries (com.sap.aii.af.ifc.filter.jar). Second parameter – custom log entry text.

Code from java-proxy and audit log after test message run example(fig.3):

ProviderXIMessageContext context = ProviderXIMessageContext.getInstance();
String msgId = context.getRequestMessageID().toString();

MessageMonitor monitor = new MessageMonitor(msgId, MessageDirection.INBOUND);

monitor.addLogEntry(AuditLogStatus.ERROR, "Its my custom Error message log");
monitor.addLogEntry(AuditLogStatus.WARNING, "Its my custom Warning message log");
monitor.addLogEntry(AuditLogStatus.SUCCESS, "Its my custom Success message log ");

Fig. 3. Custom audit log entries example.

Glad is this short article helped you with developing your own java-proxy and logging its message processing.

Thanks for help to Ivan Mamontov.

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. Ilya Kuznetsov

    Hi Ivan,

    many thanks for ready-to-use solution. Last time I used receiver Java proxy, code for handling the input shows it’s own log, not message monitor one.

    (0) 

Leave a Reply