# Implementing operations: smart proxies and synchronization

The main tool for defining implementation methods is the corba:define-method macro. The syntax is very similar to that of the usual Lisp defmethod, except that the first argument, and only the first argument, may be specialized. The formal syntax of corba:define method is described in the mapping document. There are numerous examples in the examples subdirectory. A typical define-method form might look like the following, taken from examples/test/test-implementation.cl.

    (corba:define-method testexception ((this test-implementation) a)
      (cond
       ((plusp a) a)
       ((zerop a) (/ 1 0))
       (t
        (error 'idltest:exceptionexample :member1 a))))

This defines a new implementation of `op:testexception`, which should have been defined as an operation in an IDL interface implemented by the test-implementation class. Incoming requests to invoke the operation testexception on a test-implementation instance will result in evaluation of the corba:define-method body.

## Signalling exceptions in corba:define-method

You can signal a condition within the body of corba:define-method form as normal. When the implementation body is invoked remotely, the ORB will catch any signalled exceptions and behave as described by the ORB exception API.

## Synchronization

You can interlock method invocations on a particular invocation by using the `:synchronized` keyword after the method name.

## Smart proxies

You can use the usual Common Lisp :before, :after, and :around methods. One common usage is to create a smart proxy. For example, consider the IDL:

    module M {
     interface test{
       long remoteoperation (in long fum);};
             };

Suppose we want to print a message every time the remoteoperation operation on any proxy of class test was invoked. We could do this via:

    (corba:define-method remoteoperation :before ((this M:test-proxy) fum)
     (format t "Proxy: ~s received message remoteoperation with parameter: ~a~%" fum)
     (force-output)) ; always a good idea to call this after formats which may occur in background

Now suppose there is a global variable named *call-remotely*. We can forward remote requests remotely only when this is T, otherwise we return 0:

    (corba:define-method remoteoperation :around ((this M:test-proxy) fum)
     (if *call-remotely* (call-next-method)
          0))

You can use this, for example, to cache remote state and avoid remote invocations.

## Forwarding requests

You can forward the request to another object within the body of a define-method form. The forwarding API is described separately.

## Message access

Within the body of a define-method form the `orblink:*message*` special variable is bound to the IIOP Request message that caused the invocation. This functionality is described separately.