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.
|
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 (1)
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 | March 31, 2009 2:09 AM
Posted on March 31, 2009 02:09