The Myth of "Right"

SOA Thinker - Feb 2009


Welcome to the February edition of SOA Thinker. At first I thought it would be difficult to blog on a monthly basis.
However, I'm beginning to find topics faster than I can write them down! Let's get started with The Emperor Has No
Clothes section. Here we will examine another work of fiction in enterprise software development: Getting the design right!

The Emperor Has No Clothes - The Myth of "Right"


I frequently hear people say, "With SOA, its very important to design your services right,
so that you don't need to change them in the future."
Well I certainly agree that that would be an optimal solution
if it were possible. The problem is, it simple is not possible. The whole idea of getting it "right" assumes
that things do not change in this world. If the world is static, then it's possible to get things "right" and achieve
design perfection.



In an ever-changing world there is no such thing as "right"; there is only "right now".



Of course, the world is not static, It changes constantly and at a rate faster than most IT systems can handle. The same
people who will advise you to "design it right" will also acknowledge that in the time it takes to deliver most software
projects, the requirements will change several times. That very acknowledgment flies in the face of their own advice. In
an ever-changing world there is no "right", there is only "right now". So what is a poor software professional to do?

The answer is simple to say, but not always simple to do. The answer is to design software systems and architectures
that are flexible. They should not be resistant to change, they need to be resilient to change.
This is the fundamental driver behind SOA. The world is changing quickly, your business is changing quickly, you need an
architecture that can adapt quickly to these changes.

One of the key elements of coupling is knowledge. The more that system A has to know about system B, the more tightly coupled
system A is with regard to system B. The less knowledge that system A has about system B, the less tightly coupled. Ignorance is
not only bliss, but it is also the key to loose-coupling.

In my October 2008 blog entry, I wrote about point-to-point vs.
EAI vs. SOA and tallked about tight-coupling. I want to do a deeper dive on tight-coupling in this entry. People often talk about
how tightly coupled systems
are, but rarely stop to think about how they got that way in the first place. Lets take a look at the simplest example of
coupling, two systems where system A is dependent on system B (i.e. system A "calls" system B). There is a directional
dependency from A to B. However, they often mis-categorize it as a single dependency when in fact there are multiple dependencies
at work. If we assume that system B is an EJB application, then system A is coupled in the following ways:



  • Technology: System A can only communicate with system B using EJB. This imposes a skill-set requirement on the
    system A developer.

  • Transport: System A knows how to communicate with system B using EJB's RMI transport.

  • Security: System A must authenticate in a manner that system B will accept. There may also be fire-wall issues
    if the two systems are on different networks.

  • API / Behavior: System A must know the correct method name(s) to invoke and what they do (i.e. their meaning).

  • Schema: System A must know and use the schema (i.e. object definitions) provided by system B.

  • Client JAR: System A must have the correct version of the client jar for system B.

These constraints are not all specific to EJB integration. Every integration approach brings along a similar set of coupling
requirements. I want to also point out that this list is not exhaustive. There are other ways in which systems may be coupled (i.e.
a synchronous invocation couples systems in time). The important thing to remember is that for each link you draw on your white
board that connects two systems together, you are representing multiple individual dependencies. Web services are often touted
as a technology to loosely couple systems, but in practice web services alone are not sufficient to loosely couple two systems.
Loose coupling comes from one place: architecture.



Ignorance is not only bliss, but it is also key to loose-coupling.



The key concept in loose coupling is providing a mediation layer between the caller and the system that is called. This is a
very common pattern in software but for some strange reason it is uncommon in enterprise architecture. Lets take a look at an example.
When dealing with a collection of information in Java you would normally interact with a Collection interface, or one of its
sub-interfaces like List, Queue or Set. Interfaces are mediation layers between the user of the interface and the classes
that implement the interface. As you can see, an interface, which contains no implementation logic, acts as a mediation layer
to more loosely couple the caller of the interface and the implementation logic defined in a concrete class. Without the interface,
the caller and the concrete class that is called are going to be tightly coupled. Java interfaces help to add abstraction to the
behavior of the subclass.

This principle is the core of the
Design by Contract
approach. In "design by contract", both the service consumer and the service provider agree to a specific
interface (or set of interfaces). To me, SOA is simply Design by Contract for the enterprise.

The same principle holds true in enterprise software. It is important to separate the caller of a service from the service
implementation. The mediation layer separates the two systems and helps to make them more loosely coupled. With mediation you
get something almost magical in nature, the ability to manage change much more effectively than you ever could without mediation.
Now you have much greater freedom to change the implementation service without as much concern for affecting any systems that
may be calling the interface.

So, taking what we just reviewed into consideration, let's examine each of the 6 types of coupling that I listed at the start
and see how mediation helps us to more loosely couple our two systems.



  • Technology: System A communicates to the mediation layer using web services and the mediation layer invokes
    system B using its EJB interface as needed. Benefits: system A (all callers of the mediation layer, really) no longer have to
    know how to use the EJB interface, nor be Java applications. Using web services here allows the system developers to focus on a
    single, platform neutral messaging technology. This improves agility by reducing the number of skill-sets that application
    developers need to know and by reducing the number of technologies embedded into each application in the enterprise.

  • Transport: Similar to the Technology topic above, this reduced the number of technologies at work in any integration.

  • Security: Here, web services help to avoid the fire-wall issue, but most of the benefit comes from being able to
    declare the security policies in the web service WSDL itself, making security more declarative in nature. Additionally, using a
    mediation layer like the Oracle Service Bus, you can also mediate between security approaches (i.e. convert a basic-auth to a SAML, etc).
    This goes beyond a simple interface and begins to leverage the configuration abilities of the service bus to provide mediation functionality.

  • API / Behavior: Again, web services provide a declarative and platform-neutral way to define behavior.

  • Schema: Schemas may now be managed independently of each application. This paves the way for the creation of
    canonical schemas
    and data models
    , which in turn is the gateway to the semantic web in the future.

  • Client JAR: A service provider can simply publish a WSDL online for service consumers to use. No longer do you need to
    exchange a file generated by the EJB creator.

Each of those examples taken alone provides a reduction in the coupling between two systems. The real power comes when you combine
those elements. That is when you get a noticible decrease in the level of coupling between systems. Loose-coupling is about the synergy
of applying multiple techniques at the enterprise level. There is no single "magic bullet" for loose coupling. It is always deliberate
and by design.

Ask the Experts


More scripting expertise in this months installment. This month's question
is:


How can I enable/disable proxy services programatically?


It turns out there are a couple of ways to do this. The first answer comes
from Jesus Guerra, a Senior Engineer Principal in Spain. His examples uses JMX
to connect to and manipulate the Oracle Service Bus. I'm only showing the pertinent
code snippet here, but you can view the entire class at:
ProxyServiceUtilJMX.java.



















package oracle.osb.jmx;



public class ProxyServiceUtilJMX {



  public boolean setStatusProxyService(String proxyServiceName, String projectName, boolean enable) {

    boolean done = false;



    JMXConnector jmxConnector = null;

    SessionManagementMBean sessionManagementMBean = null;

    try {

      //get the jmx connector

      jmxConnector = initConnection();



      // get mbean connection

      MBeanServerConnection mbConnection = jmxConnector.getMBeanServerConnection();



      // get domain service mbean. This is the topmost mbean

      DomainRuntimeServiceMBean domainService =

        (DomainRuntimeServiceMBean)MBeanServerInvocationHandler.newProxyInstance(mbConnection, 

        new ObjectName(DomainRuntimeServiceMBean.OBJECT_NAME));



      // obtain session management mbean to create a session.

      // This mbean instance can be used more than once to

      // create/discard/commit many sessions

      sessionManagementMBean = (SessionManagementMBean)domainService.findService(SessionManagementMBean.NAME, SessionManagementMBean.TYPE, null);



      // create a session

      sessionManagementMBean.createSession(sessionName);



      // obtain the ALSBConfigurationMBean instance that operates on the session that has

      // just been created. Notice that the name of the mbean contains the session name.

      ALSBConfigurationMBean alsbConfMB =

        (ALSBConfigurationMBean)domainService.findService(ALSBConfigurationMBean.NAME + "." + sessionName, ALSBConfigurationMBean.TYPE, null);



      ProxyServiceQuery query = new ProxyServiceQuery();



      // We look for a PS whose transport is HTTP, WSDL and qualified

      query.setTransportScheme(HTTP_TRANSPORT_SCHEME);

      query.setWSDLBasedService(true);



      if (enable)

        query.setServiceEnabled(false);

      else

        query.setServiceEnabled(true);



      // Name of the service to look for

      query.setLocalName(proxyServiceName);



      Ref proxyServiceRef = null;

      Set<Ref> refs = alsbConfMB.getRefs(query);

      System.out.println("DEBUG: Found resources that ");

      for (Ref ref : refs) {

        System.out.println(ref + " Project name: " + ref.getProjectName());



        if (ref.getProjectName().equalsIgnoreCase(projectName)) {

          proxyServiceRef = ref;

          break;

        }



      }



      // If we have found the  proxy service...

      if (proxyServiceRef != null) {

        System.out.println("Realizing changes in the session: " + sessionName);

        ProxyServiceConfigurationMBean proxyServiceConfigurationMBean =

          (ProxyServiceConfigurationMBean)domainService.findService(

            ProxyServiceConfigurationMBean.NAME + "." + sessionName,

              ProxyServiceConfigurationMBean.TYPE, null)



        if (enable) {

          proxyServiceConfigurationMBean.enableService(proxyServiceRef);

        else {

          proxyServiceConfigurationMBean.disableService(proxyServiceRef);

        }



        // activate changes performed in the session

        sessionManagementMBean.activateSession(sessionName, "Activate changes made in the session: " + sessionName);

        done = true;

      }



    catch (Throwable t) {

      <omitted>

    }



    System.out.println("End of program");

    return done;

  }

}




Java2html




Takayuki Imanishi took a different approach to solving this problem. He opted to use
the WebLogic Scripting Tool (WLST) which is based on the Python programming language. The following
script both disables and enables the same proxy service. Not very useful in itself, but it does show
you how to enable or disable a proxy service using WLST.



from java.lang import String

from com.bea.wli.monitoring import StatisticType

from com.bea.wli.config import Ref

from com.bea.wli.sb.util import Refs

from com.bea.wli.sb.management.configuration import CommonServiceConfigurationMBean



import sys

# Connect (username, password, URL)

connect('weblogic', 'weblogic', 't3://localhost:7001')



domainRuntime()



# Create a session name

sessionName = sessionName = String("SessionScript"+Long(System.currentTimeMillis()).toString())



# Get the session MBean and create a session

SessionMBean = findService("Session","com.bea.wli.config.mbeans.SessionMBean")

SessionMBean.createSession(sessionName)

print(String('Session was created ... ').concat(sessionName))



# Get the ProxyServiceConfigurationMBean specific to our session

mbean = findService(String("ProxyServiceConfiguration.").concat(sessionName),

   'com.bea.wli.sb.management.configuration.ProxyServiceConfigurationMBean')



# Creates a reference to a folder. Here 'TestCase1' is the project name

# and 'ProxyServices' is a folder in the project

folderRef = Refs.makeParentRef('TestCase1/ProxyServices/')



# Now you can get the proxy service by name

proxyRef = Refs.makeProxyRef(folderRef, 'case1_MQ1_lq01')



# and disable it,

mbean.disableService(proxyRef)



# or enable it

mbean.enableService(proxyRef)



# Now commit (activate) the changes

SessionMBean.commitSession(sessionName)



print

print('... completed')

print



disconnect()

exit()

That's all for now


Until next time, keeps your hands dirty and your code clean!

Comments:

Hi, very nice class. I'm triyng to modify it because I have a jms proxy in the alsb in a subfolder(Project-->Folder-->SubFolder->Proxy). With this method i can't get so i tought if is useful to use query.setPath(path) given path="Project/Folder/SubFolder/Proxy" Thanks

Posted by Antonio on March 30, 2009 at 07:09 PM PDT #

A thoughtful insight and ideas I will use on my blog. You've obviously spent some time on this. Well done!

Posted by Matthew Pertee on January 13, 2010 at 06:34 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

A site for SOA thought and discussion.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today