In this presentation, recorded at EclipseWorld 2008, Burr Sutter demonstrates the customary capabilities associated with an Enterprise Service Bus (ESB) for SOA-focused middleware. These capabilities include service hosting, message delivery, endpoint registry, protocol mediation, transformation, orchestration, BPM, declarative routing rules, BPEL, and rules services.
Burr also discuss enterprise integration patterns, such as Filter, Content-Based Router, Splitter, Aggregator, Wire Tap, etc. He demonstrates a technique that shows a practical application of Aspect Oriented Programming (AOP) that allows you to extend your existing Web application silos to an ESB infrastructure.
The complete transcript of the presentation has been provided below:
Burr Sutter: All right. Well, let's get rolling. We'll see how my voice holds out for this. All right. So this is 607: Advanced Enterprise Service Bus. My name is Burr Sutter. I work with the JBoss, jBPM, Drools, and ESB teams.
We're going to spend as much time as we can over the next several minutes, about 75 minutes we have together, really focusing on ESB-specific techniques and patterns and practices--things that hopefully will be applicable to some business problem you might have in your organization. OK?
The first thing I'll do is try to put things in the context of an application server. One of the most common questions I get is, "I have an application server already. Why do I need an ESB?" That's a very common question. Some people ask, "I've got Tomcat. I've got JBoss. I've got WebLogic or WebSphere. Why do I need yet another technology on the server side to help me implement my applications?"
Typically, if you're familiar with the Java EE space, and server-side Java, you've probably used tools like Servlet, or JSP. Maybe you've built a web service with JAX-WS. Maybe you've built an enterprise Java bean, a stateless-session bean, a stateful-session bean. Maybe you went so far as to build an entity bean. Maybe you've used things like Hibernate or Spring on the server side as well, or Struts, or Spring MVC, and a number of technologies, like Tapestry, Wicket, et cetera.
Those all live on the server side, and primarily are used for building web-based applications is what a lot of people focus on--either a client-server style application, where I might have like an Eclipse, RCP-based client, rich client, talking to a server-side component; or I might have a business-to-business style application, where I'm taking in data feeds from multiple sources, aggregating that data, persisting that data.
You can actually extend an application server with BPM capabilities, with rules capabilities. You'll see some of that here in this presentation. You can actually do a lot with that single container, or that single tool, if you will, that actually provides a lot of capability out of the box.
Think of it as a toolbox. You can decide which of these tools you're going to use. You don't have to use all of them. If you wish to discard some of them, right, remove them--like I don't use EJBs. Fine. Ignore it. A lot of people do that.
In the clustering scenario, you tend to have the same exact application and component across the cluster.
If I need a Servlet in a specific WAR, or I have a Stress application in a WAR, or I have an EJB application in an EAR, I will have that exact same component on ever node in the cluster, so that if one fails and dies then, actually, the load balance redirects me to another node in the cluster and the user is none the wiser. Right? They just keep on rocking along with their application. And that's an example of application-server clustering.
In the case of an ESB, however, you focus more on federation. The cons of defederation is that not everything is the same. Right?
I might have a CRM application which is based on J2EE. I might also have an accounting application that I purchased from a third party that's kind of Java EE-like but that came from a third party and I don't even have access to the source code. Or maybe I build a billing application, as an example, or a custom inventory application. Some of these things are purchased, or they represent legacy applications, like they came from my AS/400 team, my COBOL team, my Perl/PHP team, or the Java team.
How you communicate across that group of disparate sources is interesting. A lot of people use messaging. But more often than not, you use FTP. Right? You dump a file from the .NET application and upload it to the Java application, or you dump a file out of the Java application and upload it to the COBOL application, as an example.
When I say registry here, I don't necessarily mean anything like an LDAP or a UDDI registry. It might be something as simple as an Excel spreadsheet identifying how you communicate from one system to another, or an email, or a wiki page. A lot of organizations actually base their registry off that concept: a wiki page that says "This component lives over here, and you send it the file that looks like this and it's happy, you drop it in this particular file-system directory, or you have to use this FTP server with these credentials." OK?
A lot of people introduce the basics of routing and orchestration inside their application. In many cases, this is custom Java development, or some other Perl scripting. That's pretty common as well.
It might be that you simply orchestrate things together by hard-wiring them with Java code: component A calls component B calls component C calls component D. And if the business rules change, you have to go fix that Java code to reorder those components and add the new one, or take one out, or just simply move them around. OK? In the ESB world, we focus a lot on this concept of mediation.
The ESB is yet another set of tools that you apply to your Java space, right? Your Java application, your Java project. It's another set of tools that you might use. Routing and orchestration is one of those. Registry and messaging is yet another. I might have transport mediation--the idea that I can receive data not just through a Java-to-Java connection, but maybe through SOAP connections, web service, or maybe REST, or maybe FTP, or File Drop, or JMS, or something of that nature.
If I'm receiving data from these multiple sources, I have to perform some form of transformation, in many cases. If I have business-to-business partners out there, several of them are actually going to send to me a file that is unique to their needs. I need to receive that data and basically manage that data into my specific application, into my economical model.
All right? Business partners are huge drivers for this sort of application within our larger enterprises.
This is really where the ESB comes into play. Right? I can build a siloed application, in the form of Struts, Spring, and Hibernate, like we typically would do--a standard web application that talks to nobody else. But I can also now build an application that is aware of other parties within our enterprise network, or our business-partner network, and I can actually move data from one partner to another and vice versa. And that's where the ESB comes into play.
It's another suite of tools that are over and above: things like transformation, transport mediation, orchestration or routing. And you'll see examples of that throughout this session.
This is a book that I recommend everybody to read. It's the "Enterprise Integration Patterns" book. I have a screen shot of it right here, of the cover. If you've not read this book, I'd encourage you to go look at it and purchase a copy of it. It is fantastic.
If you're interested in understanding the space, and where these ESBs came from, pretty much many of the ESB developers out there have followed the patterns in this book. I'm simply giving you concrete implementations and tools that support things like splitter, a wiretap, a transformer, a business-process manager. And you'll see those listed here. "What is a channel? What does file transfer mean? What is a recipient list?" is an example.
These concepts have all been identified in a generic way inside this "Enterprise Integration Patterns" book, and they apply to the tools that you will see here in this demonstration, as well as tools that you will purchase from, possibly, other vendors. OK?
Let me put this in a little more context. I worked on an application, not too many years ago, and this is actually the last application I deployed to production. I deployed it to multiple sites--so, like 20 or 30 different sites. It was for small businesses. But it was mission critical. If this system failed, their business failed.
So what we had was a standard B-to-C, ecommerce style application: a web-based application out on the Internet, where their customers were able to purchase services and products from this organization using a web-browser-based application. OK?
There was also a browser-based application for the administration side, for the workers who were doing accounting type activities and taking back-office orders and managing orders and shipping orders and things of that nature. There was a reporting engine that connected into the database.
This is all pretty standard stuff, right? I think most people who have built applications are familiar with these concepts. Then it got more interesting. This grew over time, as the requirements changed.
As each customer would deploy it, she'd say, "Hey, but I've got this other need." And one of them said, "Well, I have to replicate all my data to my parent organization. I'm a subsidiary, if you will, of a larger organization. I need to replicate key data back and forth to them. They want to know who my customers are. They want to know what products I've shipped and received. They want to know what my overall transactions are." The parent company wanted visibility there. Right?
There was an MQ Series introduced. The parent company had deep pockets, and they bought MQ Series, and this small business had to actually connect to that. That's one example. And they actually provided two connections. They gave us a web-service connection for certain types of transactions, and an MQ Series connection for other types of transactions. They couldn't actually streamline it into one channel. They gave us two, and we had to write code unique to each one. OK?
Then the company said, "Well, I really want to use a third-party accounting package." We do basic accounting stuff in our application, but they really wanted to use something like a Peachtree Accounting for Small Business, or something of that nature. So we ended up exporting ASCII files, and the accounting system would pick up an ASCII file off the drive, and upload it. That's an example.
We also, then, had to work with a business partner, B2B situation where we specifically had to drop certain types of files on their FTP server at certain intervals of the day so they could pick up that information and actually activate other key elements to their customer base, here. OK.
So these, the two business partners, were engaged in supporting the exact same customer. It was incredibly important the data flowed properly. If we knew exactly a customer was active and had paid, then we needed to fulfill their request. That's an example.
Then we also work with a point-of-sale system which was based in web-service. This, of course, happened over the course of a couple years, that it got to this level of complexity. After that experience, I sat down and said there's got to be a better way than for each project team, who has to build an application like this, to have to write FTP code, file drop code, ASCII transformation code, MT series interaction, et cetera, et cetera, as we had to do.
One of the things we talk about a lot, when it comes to this concept of an ESB at JBoss. We want you to focus on the concept of a business process. If you understand the context in which you're operating, the fact that there is a process that governs my little application I'm working on, or my specific application component, as a service within that business process, it actually helps you to build a much better component.
You should know that you're in step four of a ten-step process. In many cases, developers don't know that, which is interesting to me. We speak to a lot of people on the front lines. They just field their little component. They really don't necessarily know how it's used in some cases. Which I think is unfortunate, and like the more people think about the architectural level. Don't have to be an architect. Still be the coder. You should understand the context in which you're working.
If you look at this simple process, here, submit an order, receive an order, and validate the order. Peel off the credit check and inventory check. If either of those fails, report back to customer service, the CSR, customer service rep. If it is OK, send the shipment, update the shipping information, and handle the accounting stuff that happens in that case. You don't actually bill the person until you ship. The accounting doesn't actually hit the books until you ship, but that's an idea.
As you look at each of those squares on the screen there, you'll see there are very specific, discrete steps. Like, par some XML for an inbound order, right? Transform it. Apply business rules to these things.
Like, I need to calculate the priority. I need to calculate the shipment status. I need to calculate the discount. If I'm doing a credit check, I might need to work with a business partner, a third party, who will give me credit information, credit score information, about this particular customer.
And I might even work, if I'm in a business to business situation, with three or four credit agencies. Even a car dealership, when you walk in to buy a car and you fill out the form, they have to shoot your application out to four or five banks. The first one in wins, in most cases, even if they're not the lowest rate. As an example, you see that sort of thing where I need to interact with a business partner, for a simple credit check example.
Now we'll aggregate the results from multiple credit agencies, apply business rules to those, and then give you the appropriate credit rating, as an example.
So the ESB is about tying these things together, and enabling this sort of business process. We often focus on the concept that a simple order management system like we described here, should not only be driven by portal application. That's typically how we think. I have a web-based shopping cart and catalog, and I click, click, click. And I hit submit. Off goes the order.
But I might have situations where people will send me orders through FTP, as an example. I have a business partner who commits 2, 000 orders a day to me. They are not going to hand-key each one of those into my portal. They're going to ship me a big old XML file, or ASCII file, or EDI file. And I'm off and running.
And it's up to me, because they're my business partner, who wants to receive 2, 000 orders a day, to consume that and manage that appropriately. It's up to the developers, like yourselves in this room, to manage that as well.
Hopefully, what you see in this slide, here, is the synergy between an Enterprise Service Buss technology, transport mediation, routing, orchestration, et cetera, Business Process Management, what is the business process content, and even business rules. How do we apply business rules to each of these individual services, rules which might even govern the routes and flows that take place within this orchestration? OK.
Let me show you a little demo. I promised you lots of demonstrations, and we're going to go forward with that. And we're going to see how all these things work, because I have a lot of stuff running on this machine at this time.
So what I have here... Let me bring up my Eclipse environment, is a simple flow, kind of like we were describing in the slides before. You can see I have received order, validate order, credit check, and inventory check. I have an east, west and central shipment operation. And right now, east and west, they're not online. They're still building those buildings. The shipping logistics haven't actually happened, yet. The warehouse is still empty, as an example.
We don't necessarily do credit checks just yet, because we haven't worked out the business negotiations with our business partner. But I can actually come in here and change the way designs are drawn. Messages flow in a different direction, now, throughout our enterprise. Let's see if this works for me.
In order to prove my point that this is not a portal-driven thing, I'm actually going to use one service to drive the other services. So I'm going to do it from the command line. I'm going to execute the process three times, every three seconds. This is actually a scheduled service, the ESB allows you to do scheduled kind of things, like ports, obviously. That kind of idea...
If this works out well for me... I think I misspelled deploy. That's how you know this is live, not recorded. I'm going to push in those changes. OK. Let's push them through the system. And you know what has happened? Because my wireless network died, my little windows aren't being updated yet because the network connection on the laptop has changed.
Let me restart these little windows, and then you'll get to see. Unfortunately, when it comes to showing off service-side technology, it's hard to see. You guys agree with that? Anyone ever tried to demo an EJB to you before? It actually makes it much more challenging. Let me restart these guys.
One problem working with wireless networks is that they come and go. Different settings on your laptop change. I'll restart, then. As you can tell, I have a lot of activity on this machine. That's a lot of JVMs running. All right. Let's see if we can get this to work now. Grade one of two. That's not all of them, but you get the basic idea. Let's see here. Number of buttons, we'll go with two. Pushing two orders this time.
There we go. They're turning away. And you can see that it's hitting receive order, central validate, ship, basically. Credit check is left out of the loop, here, inventory check is out of the loop and west is out of the loop. I think I forgot to open east, but you kind of get the basic idea.
The orchestration of where those messages went throughout our organization was dictated by this process graph, here. If I actually come in and change this process graph... All right, let's make a change to it. All we have to do is redraw the lines, when Eclipse starts to respond, here. All right. Let's go from here to here. Draw for me. That a go. And let's do this one. Switch. My challenge is I'm running a lot of different things, which includes Visual Basic running in the background.
Let's see if I've drawn all the lines. I want to connect all the dots so everybody is in the loop. All right. Looks good. Save that. And I'll redeploy this process graph. What this shows you is we're making a dynamic change to the way things flow but no Java code changes, no changes to the actual runtime environment.
The actual services still exist out there. Everything is still up and running. All I've got to do is push "new orders in." OK. Let's say we do [noise] of this [noise]. Push new orders into the system. OK. It seems like it's churning. Just check my processing image here. Good.
My little windows just won't connect to the system today. They won't stay connected. Oh, well. On the service side on the application server you can see that these different orders are pushing into the system. OK? Let's just shut those down. They are taking up too much memory.
Go away. [noise] Well, I can get them to stop. It will respond. There you go. There we go. OK?
Let's talk a little bit more about how these things work. At the highest level we have this concept of service and a series of actions which compose that service. Theses are steps which make up the logic associated with service. Most people build a service in the form of like an idea of POGO or an enterprise certain Java bean or a Spring POGO, Spring Bean, maybe even a web service.
We have extended the model to actually introduce this concept of interceptors, if you will, or like filters. The idea here is that these mediators that take up multiple pieces of functionality along the way. We might have a transformation out first and then maybe another transformation, maybe a piece of logic that is robbing or splitting.
Another piece of logic does the wiretap, as an example, or maybe start up DPM process of some sort. Or maybe invoke a business rule and have some sort of business logic. You would typically wire this service to multiple mediation points, or multiple transports. I might have the service responses, our FTP or JMS and multiple ways to kick it off.
A service can be integrated but another service to the router. The idea that service one calls service two, calls service three is also declarative and is not hardwired in the job components. You can see here that a service, the A service actually receives data through FTP but has a router action inside it which actually may have been called B service with the SOAP or C service with the CMS and the C service will actually refer to D.
You can have a static wire or a dynamic way. That dynamic content based router, as well as static recipient list that you can also define. The overall idea is you have all these different tools, those different actions, those different services and all these things that are capable, capability right out of the box, to enable you to build this application.
You have a number of different transport mediation capabilities. I want to receive HTP or I want to receive SOAP or I want to receive JMF. These are new ways to create an event and admit an event to VSP. The VSP is listening to all these channels that you can figure and support inside your container.
Once you receive that data, you might want to transform it, route it, secure it, manage it, store it, and register it.
[audience comment off-mic]
Is VSP synchronous or asynchronous? I think the question is. And it is both. Primarily asynchronous is what we recommend, but if you truly have users waiting on the other end and a portal like application, you can also have them wait, lock the thread, respond to that thread.
Everything is ...
[audience comment off-mic]
In the case of ESB everything inside this architecture is asynchronous and non-blocking. So everything is based on some queuing mechanism. Even STP is a queuing mechanism. If you don't use any of these channels, we have the MVM queue as well.
Everything is queued. But if you do have users waiting, you have to find a way to pause that servlet thread and wait for a response before you get back to the browser. Unless you use some form of AJAX technology to respond asynchronously to the browser.
[audience comment off-mic]
OK. Orchestration can be done through JPDL and there's also an event notification for outbound information. BAM and CDP are features for us, concept of CEP complex event processing. [It is] the idea that you can look through all this deep different data points flowing throughout the system and make decisions about those in real time. On the right hand side of the screen we have the concept of business services.
What do you doing you business logic in? You build your business logic in Java, POJO, but you also allow you to build your business logic in things like Jython, JRuby, Decision Tables, which is an Excel spreadsheet, maybe your own custom language in DSL that you want. There are a lot of different ways you can build the logic of these mediation points or your business logic. It's a very flexible model.
Now I'll show you an example of what that means in a second. Transformation is based on the Mile and Smoots project. The idea here that you can do Java to Java based transforms, where I actually have a Java component on the left side and a Java component on the right side. I'm simply mapping the data from one property to another.
But ultimately what you are going to see in the transformation is the XML transformation. I have an XML document that comes in from a business partner. It does not meet my internal canonical model. I'll map that in accordingly. Then I'll have things like, maybe I have an ASCI file, maybe an EDIS file, which is sent to me, and then transform that to an XML model.
Or even a POGO model. It's very common in a lot of our demonstrations to see, take the intake of XML to match to the POGO, as an example. That's one of the more common things that we do. OK? So you can...
[audience comment off-mic]
There's no specific ontology syntax in the Smoots. It's pretty much just the transformation engine itself. You can define ontologies around that, and surround that with your own business content.
[audience comment off-mic]
No. It's not specifically that. It actually uses Java at its root level. You are using some form of parsing whether it be a DOM based parsing or SAX based parsing. OK? The concept of service logic like we mentioned earlier could be based on Groovy or Jython, or JRuby or Bean Shell. There are a lot of different ways to write logic.
I use Groovy in a lot of my presentations on a lot of my coding efforts. Groovy does a nicer job than of XML parsing than Java, as an example. But you'll see situations where if I need to parse XML, to get the information I need out of it, I'll use a Ruby script for that instead of Java.
You use the right tool for the right job. Maybe some of these tools are more applicable for your business context. Like the concept that I can actually declare logic in an Excel spreadsheet might be very useful for my business analyst, as an example.
Let me show you an example of what that means here. I'll run this one. The idea behind this one.... We'll let it load up... is that inside a service you can see this is... I'm just showing you blocks of XML outside the tool. But I have a service declared here.
I have a service that's declared and has a Groovy listener, which is a Groovy client, which just popped up on the screen. That's so I can interact with it as an end user. It also has a JMS channel with it that it's listening on. Then it has this concept of a series of actions. And the actions represent a Bean Shell, a Jython, a JRuby and Groovy. Then, I have this iTunes thing. But since the network is acting up I won't show you that.
In this case the Groovy script will go out to iTunes, download the latest information and then bring it back into the actual stream of information. That can be part of your response. A service might have one action, right? But these are your mediation tools. This is where you will transformers go online. This is where your routers go online. This is where you implement those enterprise integration patterns. This is where a wiretap would appear, as an example.
[audience comment off-mic]
A specific service is central to a specific container. But you can have copies of that service in multiple locations.
Audience Member: Do they share state?
Burr: Shared state? No, services do not share state. Services are inherently stateless. There is a possibility to share state if you choose to, but by default they're stateless. You can see here, I'm poking messages in. Let me pull up my server-side console so you can actually see it there, too. As I send data in...
Then it's just simply applying Beanshell J--that's all those scripts do, is simply take the current message and add a piece of data to it. That's all it does, another string. So it's a simple example--it's kind of a "Hello, World" example--but you can see that there's a lot of power in this concept where we have mediation points. I can add mediation points to introduce JRuby, Jython, transformers, wiretaps, etc. That's part of the architecture of how this is written.
Could you write your own servlets to do this sort of thing? Absolutely, but you'd write a lot of code. This is stuff we have out of the box, pre-built, available to JBoss users, as an example.
A very simple example, and if we wanted to go play with it some more, we could. We come in here and specifically do things like... Let's look at it.
Let's make a simple change to it. Let's drop the JRuby out of it. It's no longer in the chain of events as that data comes in.
We deploy it... You can actually make these changes in real time in the production environment. I'm actually changing it and pushing it back out. In the production environment, you can actually make a change and see the change in real time, if we want. There's an asynchronous request and here's a synchronous request. You can see that the Ruby is now gone from the list. This is an example of the answer to your question earlier about, "Can you do things asynchronously or synchronously," and the answer is both. What happens in a synchronous request is it sends two one-way asynchronous messages. One inbound and one response on another thread. Your client, though, has to be written in such a way that it understands that model.
Simple example. Then, if you look at this Excel spreadsheet, the concept that I can have a domain-specific language... You can see, "When there's a driver, ages between 18 and 23 years old that has had more than one prior claim, and then reject that policy with this explanation."
That's an example where you have worked to define your own specific domain language that your business analyst might use to actually script the logic associated with a particular business decision. Or you might use an Excel spreadsheet known as a Decision Table to also enable that business decision.
To show you what that looks like, so you can see it in real time... Let's do that. Let's go run it.
I have my spreadsheets already running here. You can see that there's a priority. If the status is greater than 40, at least 40, and the total is over 50, we put in an order priority of four. If that order priority is four, we give you a 16.8 discount. These are actually Excel spreadsheets living out here in my deploy directory. If I open up that archive... We have the ability to have exploded archives in addition to zipped archives. You can have a zipped WAR or an open WAR so you can actually go edit the files directly inside the file system. Here's where those Excel spreadsheets live. If I edit those, I can then push and... Let's go ahead and make a change to make this more interesting.
Let's make it...26.8, in this case. There we go.
And run the--push a message into it. In this case, I'm not actually using the little GUI; I'm using a command-line tool to push the message in. You can see the order priority came out as four and the discount is 26.8. If I even wanted to add whole new rules, I could do that. I could say there's an emerald customer whose status is greater than 40, whose order total is greater than 200, who uses a priority of five. Save that, and I could go apply discounts to that as well.
So again, the emerald customer, priority of five, might have a 78.8 percent discount, as an example. All I'm doing is I'm editing Excel spreadsheets, in this case, to change the data or change the business logic--in this case, the business rules--and push that information in. You can see it takes a little time to compile those spreadsheets. There's priority five, and there's 78.8, as an example. Again, we have different models to solve the problem. We try to show these things to expand your horizons a little bit. This might be something that's appropriate for your particular business case, the ability to have business logic expressed as rows in an Excel spreadsheet, as an example.
That's a capability that comes from our Drools project.
One idea that you have in the Enterprise Service Bus world is this concept of proxying and being able to absorb external resources. I might have existing web services that are out there that I need to consume, and I might then reproduce those web services to the outside world. I might also consume existing EJBs, existing POJOs. Or in the case of my little demo, an existing Ruby script, as an example. I might consume that inside my service, and then I republish that to the outside world on, perhaps, a different channel. I can consume a web service and push that out to a consumer through JMS, as an example, or FTP. I might receive SOAP as a web service, and then I can push that back out to some back end system through JMS.
The idea of ESB is that it connects the dots there in that case. The consumer is completely unaware of what the location is of that service and what the transport is of that service and what the needs of that service really are. The service is responsible for actually taking care of the transformation, the transport mediation, etc., and the ESB provides that capability.
Here's an example of a web service that we've done. You have two ways to build web services in our container. You can do a 181 annotated endpoint the way you would do in Java EE-land. You would actually say things like, "Here's my .java file," and you'd put @WebService, @WebMethod on it. That's all you do. You annotate it and it becomes a web service.
In this case, we have a new declarative way, all through XML, to do a web service. If you look at it here, you can see that I simply have defined an inbound XSD, an outbound XSD, and those are the contracts that now govern this service. If your message comes in without the proper syntax, you're going to get rejected, as far as the XML goes.
It also generates the WSDL from this information. To be a web service, you have to have WSDL, right? Otherwise you're not really a web service. In this case, the web service is automatically rendered, as an example. I'll show you what that looks like. We go in here... Let me see if I can find this guy.
You can see it's the request XSD, which is the inbound request. The customer XSD is the response. This is my customer object that I've identified here as an XML schema. I might populate this object from the database if that's what I want. In the case of this little demo, it just populates it through Java. But you can see that the idea here is that I can actually create a fragment of XML, have a schema associated with it, and then respond to a request.
This guy's already up and running. By deploying him, you get WSDL automatically. Here's the WSDL that was rendered from that little object you saw earlier. You can see "first name, last name" is the response as a complex type there in the WSDL.
To prove that you have a valid web service, you can certainly test it with Java, but if you're doing Java to Java interactions, you probably don't need web services. That's a common error people make. They write Java code to talk to Java code, and they use a web service for that interaction for some reason.
Typically, web services are best for business-to-business kind of relationships, where you have an external party that is interacting with one of your components, and you're exposing it out through your firewall. But in my case, I have a lot of users who are very interested in using .NET on the client and then Java on the server side.
I built this little VB.NET application. You can download this Visual Basic Express from Microsoft's website, it's free. And please don't start getting scared, or running out of the room. This is Visual Basic, but it's OK. Really, it's not that bad. Some people just hate Visual Basic, I know.
If you look here, you can see there's a reference to this ESB service. All it does is point to that WSDL, the same WSDL I was just showing in the browser. It's making an HTTP request to get the WSDL from the server side, loading it here, and generating a client-side proxy for me.
If I look at the code behind this button call here... If I can get the Visual Basic now to swap into memory... You can see that, in this case, my request is based on ESB service, customer request. I have data from the text box that I'm going to send to the service, so textbox that text, grab it off the screen. I have a customer that I create. I'm basically going to say to my proxy fetch customer operation, with this request populating this customer, as an example. And then I display that customer.
What's interesting is, if I do things like my proxy, OK, as this thing learns to respond to me, here. All right. If I say my proxy, you can see there's the customer operation, there. Or if I even type in ESB service and hit dot, you can see customer object and the various operations that are there.
Those things that were Java are now available in VB, to the VB programmer. That's the beauty of a web service. If I'm a Visual Basic guy writing an Excel spreadsheet macro, let's say, I'm talking Java without knowing Java. I'm speaking Java without ever seeing Java, because it's all proxied through the web service engine.
This is the capability that made web services so strong and so popular. But also one of the things that also made it the most hated. People thought they needed to do this for Java to Java interactions, too, which is not necessary. Java speaks Java. VB doesn't speak Java. But services are what bridge that gap.
In this case the web service that we have on the server side is now the web service written in Java, written through the ESB channel, can now respond to Visual Basic requests coming in from the client. I'll go ahead and launch the client application, assuming I didn't make any errors there while I was playing around with it.
If we look at my server-side console, all right. If I type in 10, which is the ID of the customer I want to fetch, you can see Visual Basic comes back and says, oh, 10. Jim Smith. Right. You can see the number 10 on the server-side console.
Visual Basic is making an indication of the Java for a simple web service that was all declared through XSDs. And ESB is governing that, managing that. That same service logic can also speak GMS, or FTP, can also have content disrouting, transformation, et cetera. OK. We'll keep marching along, here.
Other examples of how to proxy in EJB, keep open existing service-side architecture already, maybe it's Spring, maybe it's EJB. Theirs can be proxied into the ESB services, also. Now this EJB, which, historically has spoken RMI, RMI over IOP, because that's what they do, now can speak FTP, it can speak SOAP, it can speak JMS. All right.
By simply laying in this specific action, what actually provides the proxy, and provides the capability through the ESB service in this case.
Also, if you want security, you might want an additional layer of security at the service level. If you have these services inside ESB that are proxying web services that are running on your enterprise, EJBs that you have out there. [You have] EJB running on Web Logic, EJB running on JBoss, etc. and Spring Beans.
You can then add an additional layer of security to them in a declarative way. You can actually say what this security module is, and what are the rules allowed to invoke this service in a declarative manner. So it's only if the message payload contains an authentic and a user information, but also an admin role or human resources role, do they get in.
If they are not allowed in, they get rejected. OK. They get thrown back. That might be something that you need to take advantage of. In our case, our implementation takes advantage of Jazz, our Jazz implementation. Which means you can actually just update the file, a file with actual user IDs and passwords. Or you can actually just update a database row or table.
You define the schema, maybe an LDAT if you want to be real fancy about it, or even your own custom implementation for an authentication module. OK.
There's monitoring and management in all this. As you can see, there's a lot of complexity here. One of the issues is if I have 400 services out there, some using Ruby and EJBs and Spring, and some using Web Services, some using JMS, et cetera, et cetera, in a federated architecture, how do I keep my hands around all that?
That's a lot of complexity you have to worry about. We only recently learned how to manage an application server over the last few years, in many cases. We knew how to do database servers back in the early '90s. We learned about application servers around late '90s, early 2000, right? And we learned how to manage those things.
Now how do we manage this ESB, which is an even more complex beast, and has more capability? The idea is we introduce a federated monitoring and management technology. This is based on hyper technology. Again, this is a technology you can find on JBoss.org and download today.
You can then see, in a central console, all the resources that are running around your network. You can see all those ESB services and you can drill down on them and figure out what their performance characteristics are.
This is the architecture that we employ in that case. We have a centralized server running the JBoss operations network server. It has a database. All right? Then it has a little agent that lives out there inside the server, not inside the JVM, but inside the server that these things are running on. This concept of federation, not a cluster, clustering is different. Cluster is where everything is the same.
Federation is where things are unique. I might have a series of warehouses that all have their own unique services. I might have a customer service set of servers. I might have a rules set of services. I might have an order management system with its own set of servers. That's an example of federation, which is typical within a larger organization.
Typically not every server has the exact same things on it, right? So the idea that you can communicate back and forth using these agents into a central server, allows using visibility and also allows you to push changes out to those servers as well. Here's a new service. Deploy it.
[audience comment off-mic]
Burr: In this particular case, where-that's a very good question. We're actually using HTP in this case, plain HTP. Nothing as fancy as ESB. We've discussed that, but we've found that no one really has need of that yet.
Audience Member: For security?
Burr: Yes. This is all encrypted, server encrypted, and authenticated through HTP. HTPS and HTP authentication. OK. The concept of routing and filtering. The idea is that I can actually bring information in through a channel, transform it, massage it, run these different actions associated with it, and then execute another service out there, like the platen service, special handling service, based on the content.
I'm receiving data from various business partners, these are orders that are inbound to me. And I need to review that information and make a decision about where it should go. I might have a special, high-priority customer service team.
Or I've worked with companies just recently that actually handled very interesting shipments. You know, if they're sending munitions for the government, there are very special carriers, certifications for the drivers, there's very special ways you handle that transaction. That's a different team of people that handle it.
You need to route that order, that request, to the appropriate group of people, as an example. If you're shipping things that need to be kept cold, right, that's another team of people that have to make sure the food doesn't spoil before it gets from point A to point B.
This idea of routing is something we do in our regular business world, we do it inherently. In most cases it's humans making those decisions about what goes where. The idea that the ESB can actually make a decision in real time, and calculate the next destination, is routing in this context.
Let me show you a demo of that, give you a feel for what that looks like in reality. OK. What I'm going to do here, if I set this up correctly... This is a very simple example. OK. The idea, and I'll just show it in a very simple way, is a series of rules. If a status code on the inbound order is zero, go blue. If it's two, go red. If it's one, go green. Pretty simple rules, but I'm just trying to show the concept.
If the XML contains a zero, a one or a two, pick the appropriate destination. These are actually going to be other JVMs that are running out here. We'll get those executed. So they're running, and they're going to be listening, looking for traffic, looking for things that are of interest to them.
These could be your different customer service teams. Red team, green team, blue team, as an example. Their systems will pick up this data feed and run off with it. But first I have to push something in. If I look at my sample order, here, you can see it says status code of one. That's the XML order that's inbound. If it's one, go to the green team. OK.
Let me push the order in from the command line. We'll send it in, it will hit the ESB service on the server-side, here, and then it routes out to the green team. The funny thing about these four windows you see is that these are all external to the ESB itself. There's a client-side JMS producer pushing personal messages out, and there's these three JMS listeners. It can be FTP, web services, or whatever. I just chose JMS for this example. But I can push the data in.
If I change the data now to two, the rules say to go to red. We want to push the new message in. Alright, that's the connection to the server. It grabs the data off the hard drive and pushes it in. The router sends it off to the red listener in this particular case.
If I wanted to, I could get really fancy with it and change the rules altogether. Right now the order says two. Let's put the two to blue, zero to red, and one to green. Zero, one, and two, we've still got our three settings there.
Now I push in the data. I believe I made it change the right file there. I can go in if we change the rules to respond to business changes. What if the green team went on vacation, or better yet, at seven o'clock they go home? I need to now route data to the agent team. At seven P.M. their time, they go home, and you route the next transaction to the European team. There's following the Sun model, for example.
This idea of having declarative logic in a simple rule-based language like this, as opposed to hardwiring those things to Java, make it much more agile for me. I can make changes to the process flow, or flow of events. I can make changes to routing logic, all simply by updating files, as an example.
A little bit more. There's a concept of load-balancing and fail-over as a higher-end capability of an enterprise service bus technology. We might happen to know whatever services you're executing, an order management service, a customer credit-check service, a business-rule service, or a routing service. If multiple instances of those services are out there on my network, we know where they are and we can route and load-balance them accordingly.
If have three versions of this discount service, and I have received 100 requests, I'll send 34, 33, and 33 by default. You may choose not to do that, and you can actually choose the load-balancing algorithm. But by default, out of the box, it's round-robin. You send everyone an even number of requests if at all possible.
It would even be true if these guys were on different transports. This one might be on FTP, because it's running away out there beyond the firewall. This one might be SOAP, it's proxying some .NET applications. This one might be JMS, as an example, and that's OK too.
The idea that you have load-balancing and redundancy means that if you have one service endpoint go down, this container went belly-up or the server hard drive or memory was fried, then you're still OK. You can still process the orders that you're receiving for your organization.
In ESB, built properly, as an advanced technique you can also provide this kind of capability. This is what you're used to if you're building Java EE and J2EE applications. Your server components do this, and your EJBs work this way. We applied the same model to the enterprise service bus environment.
For transaction processing, in this case you do have two PC-style transactions in certain situations. For instance, you don't get a two PC transaction if you used file drops, because the file system isn't transactional. It won't enlist the transaction manager. But JMS would be. It really depends on the context of what you're looking at.
[audience comment off-mic]
Burr: Yes, one inbound queue, multiple services actually competing essentially for messages. If you're using a queue, the message is only going to go to one of those endpoints. But if you're using a topic, then it would go to all of the above. You have options for both. You might use a fan out metaphor if there's another pattern, and you would use a topic in some cases. But we also have a sprayer hooked into the ESB if you wanted to use the router. With the router, it doesn't have to pick one destination like the demo I showed you. It can pick 25 destinations or groups of destinations if you want. It's very flexible.
The routing logic is where a lot of this is expressed inside the enterprise service bus, the ability to actually say load-balance it. The router is clever. It says, "That guy is down. Shoot a message to the other guy."
A common question I get is, where BPEL fits into all this. I'm just going to take you back a few steps. Back in 2002 you guys heard that SOA was all about web service. You had to do web services. I met organization that literally put web services everywhere.
I was called into a consulting engagement at one point where the gentleman said, "My system is very slow. We can't process the number of transactions we're supposed to. Users are waiting. I've got customers waiting online for this web application to respond."
I sat down with the architect and said we'll just get on the whiteboard and start drawing pictures. That's the first thing you do, get on the whiteboard and draw pictures. We have a browser, great. How does it communicate, HTTP. GET, PUT and POST, no problem. Tomcat server container, great. Struts, no problem. Spring, we're good with spring. Hibernate... We're drawing pictures.
Then he threw another box between the Spring layer and the Hibernate layer. "What is that box for?" "Oh, that's a web services layer." What he was telling me is that every transaction that goes through his system comes through HTTP and hits a serial container. Now it's Java component, a Java thread that then executes a Spring component that then has to marshal to XML, and then use HTTP to then go to Hibernate to get the data from the database.
You've added a network hit and a marshaling of XML just for what reason? "Our business partner is using these web services?" "No." Nobody was using these web services. "Are you running across a lot of JVMs and maybe .NET clients?" "No." No, it's all Java. OK, let's rip all the web services out. They took advantage of the technique, but they didn't apply it correctly to the problem space.
Everyone who has to do ESBs has to do BPEL. It's much like in order to do SOL, we had to do web services. In the ESB world, we have to do BPEL. That's not true either, much like it wasn't true that everything had to be a web service.
The idea of BPEL is a phenomenal web services orchestration language. It does a fantastic job of that. But it does not solve the problem of human task managing, or of dealing with things like JMS or FTP.
If you look at this picture that we drew here, the idea was that the enterprise service bus might actually have an orchestration layer, or a composite service layer, taking advantage of the tool you saw earlier. I'll show you another example of it. It uses JPVM or JPDL to integrate these services. It might be JMS-based or FTP-based, or even web services-based.
Then you might build that service out with Groovy, Rules, Spring, and EJBs. But all of that is one composite service exposed to web services with Wisdel through the partner link through BPEL, which is orchestrating some global thing throughout our enterprise.
Ken, Would you use BPEL at this layer here? You can. But people I've talked to who have done that haven't been too happy with that exercise, because it's slow. Everything that goes through BPEL has to be through a web service. It all has to be XML, and it all has to be Wisdel.
I may have Java component one in my customer service application talking to Java component two in my human resource application, just to figure out who the employee is and see if they can work with this customer. I don't necessarily want to put that through a whole BPEL process.
Again, use the right tool for the right job. It can be applied in this context, but it's not necessarily the best thing for the demonstrations that I've showed you here.
There's one last thing I'll show you, and then I'll show you a fairly big demo of this. Hopefully there won't be any performance problems with it as we've had here in this little session. It's idea of a splice technique, AOP.
I've been promoting this concept of an enterprise service bus. One of the things I often get entangled with when I talk to people is that they tell me, "We're a Struts shop. We don't know how to do an ESB. We're Struts, or a Spring shop, or Seam. We like JBoss and do Seam."
What we've showed you how to do with Struts, Spring, Seam, and all those other tools is how to build new silos. Every book you pick, everything you read, every blog posting etc. for most people in the industry is how to build a new silo.
Look at Ruby on Rails, it's a perfect example. How do you build a new silo fast? The idea that you're building silos means that you now have to integrate that silo into the rest of the enterprise as your business climate changes.
I am going to show you. I took the Spring Pet Store, which in this case is a siloed application. By that I mean that it has a web layer, a middle-tier in Spring, a persistence layer in iBATIS or Hibernate, and it writes to its local database. This is a siloed application. It doesn't realize that it is operating in the context of a business process in a wider enterprise.
You can use AOP to add interceptors, or Aspect-Oriented Programming. I found the one use case for AOP in a simple business context. Normally you don't care, as a business application developer, about AOP. But in this case, we use AOP to steal data and eavesdrop on a siloed application.
Let's see if this guy is going to run for them. I'm going to leave these guys up a little more. Alright, let's close those down. It gives us a bit more memory. Let's see if this guy is running.
This is the Spring Pet Store application. You've probably heard of the J2EE Pet Store application, but this one has been Springized. The EJDs have been removed, and it has Spring beans instead, as an example.
The reason I show this is because all the people are familiar with this. I didn't have to write my own web application, but just took one that's out there. I didn't even have to have the source code to it, because using the Spring AOP, I was able to intercept the inbound order through the silo and route it to the ESB through JMS.
If I come in here and say "Add cart", there's a $193.50 Amazon parrot. I proceed to checkout. Let me do a couple of other things here to get ready to receive this order. Let's make sure we're ready.
I have a lot of other things I could show you, but I'll just show you this one. I want to pop up my little monitor again, so that you can actually see the data flow into the system again.
What is happening--and I'll show you this too--is that there's a business process that now backs up this particular business transaction. The data is going to flow into the system, and then business rules are applied to this business transaction.
I need to receive the order, my human to review the order, I need to calculate a discount, I need a human to review the discount calculation, and I need to ship it. I need to work with my third-party shipping partner, because I'm not going to ship it. That means that I have a business-to-business transaction there as well.
Let's make this work and continue. We'll login and just take out my default information and hit "Submit". You can see the priority of 4. Again, the silo doesn't know about this little guy running over here. Think of it as the wiretap pattern that we spoke of earlier. I'm eavesdropping on the application.
1275, all the information in this order was routed to the ESB. The ESB then routes it to the business-process management system. I can go over here. Oh, it timed out. Let's log in.
You can see that there's 1275 executing there. The 1275 is in process. It's executed. It's actually persistent. It's a long-running business process, and so if I happened to blow the system up right now and come back to it, you'd still see that ESS still says "running". There are no held threads or blocked threads, like the question we asked earlier. They are simply held in a persistent state.
If I look at the process image book, this is the image for the whole process. Let's look at this specific instance. You can see that it stands at the Review Order note. That's where it stops. It's paused and is waiting for a human to interact with that.
Now I look at the process variable. You can see that there is the original XML that came in. It was still under AOP. Then, there's data that the SOP and business-process system care about. I care about order total and priority, because these are important for other downstream decisions that have to be made.
Some of the data has been parsed out and put into individual buckets in this case. If I go to my task and hit "Examine" and "Save and continue", you can see a little window here where a little activity happens. The discount is calculated at 18.9.
If look at my process image again, you can see that it's at "Review Discount" now and is paused at that point. It executed this ESB service to get the discount calculations and execute the business rules. Like you saw in my earlier demo, I could have executed those rules like an Excel spreadsheet. Maybe that's how I defined it.
So, "Review Discount". I go back and say, "As a human". This is your back office employees interacting with the process. I'm going to approve it. This is a content-based router, and based on the type of priority and order amount, I'm going to put it to a different shipping partner and wait for it.
We look at the process instance and the image. You can see that it's here "Ship and close". Before we actually have this concept of these asynchronous images being invoked to invoke these ESB services, in this case we now have a situation where we've invoked the ESB services but we're waiting. We're not waiting on a human, but on the service.
Again, it's asynchronous, with no active threads, and all persistent. The idea in this case is that the shipping partner is a business-to-business partner situation. I sent them the order. They have my warehouse--I don't own the warehouse. They have all my products in their warehouse.
They ship it, and at some later date they respond. That date might be an hour from now, a second from now. It might be a day from now. It depends on what they have to do to ship it. That's all within our business plan.
When they have shipped it, they drop a little shipment notice on my file system. I have to emulate a business-to-business situation on my laptop here. There's a little thing that shows up on my laptop here on my file system. That is the shipment notice. I purposefully had it not hit the right folder.
Now, if I move it to the right place, which is where the ESB is listening, the front warehouse folder, you can see on my little monitor "Received shipment notice". If I just refresh the browser here, the business process has ended.
It's a concept of using ESB to not only get things out of siloed applications, but also to wait for things like a business-to-business thing with FTP file drop and JMS etc. in an asynchronous manner. It's also very powerful.
Let's have a little more fun with this and make it more interesting. Let me modify the business process. I'm getting lucky at this point. Most of the other demos ran.
Let's put this in here. Here I'm going to add a state. We showed you the OK path, where the user agreed to approve the order. What if they reject the order? If we reject the order, let's say that we need to call the customer.
What's interesting about this now is that there's a series of services which back up this business process. I'll bring you over to this thing here inside Eclipse. It becomes fairly complicated.
The startup service was the guy that is basically receiving data from the Spring application. He's the eavesdropper. The intake service is responsible for things like discovering the message origin, transforming the message to our canonical model, and doing other parts of processing. These are a series of steps and actions.
I can display it. I also have a business world processor. This guy calculates the priority, as an example. It runs a priority calculation using business rules, and then also alerts the monitor. That's how the little guy on the right-hand side of Stream has been invoked. The monitor gets invoked with every service call.
In this case, I also have a rejection service that's loading out here. It's just sitting out here, but it's not being used. What I need to do, is in this ESB service node, we're going to call the rejection service. If I look back at it--let's look at "rejection service"--you can see the rejection service is in the "rejection" category.
Services are always in this category name concept. You always do this in a declarative manner. You don't say that that's JMS, or TCP/IP, or FTP, or SOAP. You simply call it by name. I'm going to call the rejection service in the "rejection" category by name here, like that. I think that's pretty good so far. I need to wire this up. Add some transitions: to reject, call customer. And then we end the process.
Just like the business process exists now, we might have a rejection path. Now I've added a rejection path, and I need to modify the screen that pops up. The user only has an "approve" button, so I need to give them a "reject" button.
Here's the review discount screen--and this is all using JBoss Tools, as an example. JBoss Tools, which are available on JBoss.org. What I'm going to do, is I'm going to copy this "OK" button, paste that in. It's going to take the "to reject" transition.
Here we go back to our business process definition. See, it says, "to reject"--that's the name of that transition--while this is "OK." So "OK" goes down one path, "ship to reject" with the "reject" label goes down the rejection path. That's how we branch the process flow in this case. We can make a decision by a human.
We showed you how to make decisions by rules to do things in real time, automatically, and in this case we have a human making a decision. I can deploy this, now, back up to my system. All happy and deployed.
If I did that well, we go back to our admin console here, and we look at the number three. Let's see if this is the right one. All right, there it is. There are the changes that I made. Let's take another order now.
We're going to take another order, here. I can order 10 bull dogs. Trying to get that amount pretty high, there. OK, make a change, hit "submit." You can see priority four for order 1276.
Let's go over here to our business process. There's 1276 in execution. Let's look at the image, and you see it's for "view order." Let's review it. I'm going to hit "save and continue." I reviewed it, and now I'm going to go look at the next step. It's a "review discount." OK. We'll go to our tasks. The discount is 18.9, and now I want to reject that. I have a "reject" button, I take the rejection path, and you can see it says, "Reject, reject, bye-bye."
If I look at my process instance image, you can see it says, "Call the customer." It's no longer waiting for shipment, it's now waiting for me to call the customer. In which case, as a human, I pick up the phone and I call, and I say that I've completed that task.
Again, the whole idea here is that you can make a lot of things happen within the ESB context. We can listen in, we can do transformation routing, transport mediation, etc.
But we're going to also use the concept of business process and long-running process, where we're orchestrating services and humans in an individual flow, a single flow, which is something you don't normally do with other solutions. You can have the rules engine, which is the way you express logic in many cases. Calculations, routing logic, making decisions around priority calculations.
That is all of my demonstrations and content at this point. I know we're also out of time, but I'm happy to take questions for you guys for anything you might have. I know we're running a--it's lunch at this point.
Audience Member 1: What version of JBoss?
Burr: What version of JBoss? What you saw here in this execution is basically JBoss 4.2 App Server technology, and JBoss 4.4 ESB. Two separate projects on JBoss.org. ESB 4.4 and JBossAS 4.2 combined. You can actually run the ESB standalone, but I combined them to give you all the capabilities here that you saw today. You can actually host ESB in the App Server container. ESB, by the way, also comes...
Audience Member 2: JBoss is 4.2?
Burr: App Server 4.2 and ESB 4.4. [audience comment off-mic]
Burr: The ESB, 4.4. Yeah, if I had an Internet connection, I'd show you where these things are on .org, but it's acting up today.
[audience comment off-mic]
Burr: Absolutely. One of the things I should have mentioned with this is we expect you to change this. This is based on a JSS-type application. But the jBPM API is very rich. You can say, "Give me the task for this user." You can say, "Start this process." It has a nice API, you can just include the JAR in your Struts application, your GWT application, whatever you're building your web client in. Or not, you could be a Swing-based client if you want, and you can interact and get the exact same user interface you see here and give it exactly the way you want it for you user. We expect you do that. We expect you to tear this apart or use it as an example of how to use the API.
[audience comment off-mic]
Burr: So, as far as... [audience comment off-mic]
Burr: Right, so if you have the situation where it's a long running-type transaction... In that case, you don't want to lock up resources, like hold database locks, you don't want to lock up threads, things of that nature, because it might be that it takes two days to complete the business transaction. [audience comment off-mic]
This is no longer an easy thing to do. [laughs] If you have a very short-lived transaction, you would use standard transaction things like you use in J2EE-land. If it's a long-lived transaction that lasts multiple days, you have to actually then build your own compensation routine for that.
If you use something like jBPM, as you saw me do in my example, you'd know the path that you took. You would then have to decide, "What is my compensating routine to deal with the situation?" If I've spent two days, and I'm a day and a half into that two days and things blow up, where do I roll back to? Do I roll back to day one and start all over again the two-day process, as an example?
That concept of having to introduce compensation hooks into your app is something you have to code today. That's something you have to write Java code for. Everything I showed you today was stuff you can get out of the box, you don't have to write hardly any code for.
As a matter of fact, that last big demo I showed, it could be 100% non-Java. But if you want to do the concept of a long-running business transaction and you want to identify specific rollback points, you have to write some Java code to determine what to do in the business context. If we were to ship goods, we can't really roll back and not process the accounting records. You have to make that business decision.
We're also working on a technology for WS-BA -- Web Service Business Activity -- which is the WSDL web service way of doing a long-running compensating transaction, as an example.
We have JBoss Transactions, which is another project at JBoss.org. We can go get that technology, but it's not in a supported form at this point. It's just purely on .org. That's why we don't talk about it that much.
The technology I showed you here today, we also support. If you have a support subscription and you want us to take care of you on these things, we can. In the case of WS-BA, that's still a little bit experimental stuff.