1. First of all, what is Eclipse RAP? It’s the Eclipse Rich Ajax Platform 2. It allows you to build web app “the Eclipse way” 3. RAP is to the web as RCP to the desktop. It inherits all the goodness from building a RCP app, such as extension...SWT/JFace, as you may know, JFace is a layer sits on top of SWT to provide MVC programming model, and of course, the componentied OSGi design that we have talked a lot about in our study group 4. For tooling support, RAP tooling has become a default component of the RCP bundle in Helios, it includes RAP target platform, launching, debugging, exporting war, many many other features
1. As u can see below, the only difference between the architecture of RCP and RAP is the implementation of SWT and RWT 2. but the implementations for RWT are web specific. For example, Display.getDefault() returns a session-based Display 3. No SWT APIs are changed, 4. And RWT is not a patch fragment to SWT, I thought it is a patch fragment, bu some reader of my blog post clarified this with me
1. Thanks to RWT, RAP brings RCP apps to the web with little code changes. You basically need to make adjustment, such as making your implementation session-based. But you still reuse most of the RCP codes. We call this single sourcing. 2. RAP app also has all the benefits of a OSGi-based app. 2. First of all, building web-app is a process of building plug-ins and bundles. During implementations, you always think how can I make this component extensible, how can I hide this implementation details from other components. Then in the end you build an extensible and highly decoupled web apps. 3. UI side... 4. Server side... 5. Another cool stuff I wanna mention is, OSGi allows you to dynamically enabling/disabling bundles, I am thinking if we need to upgrade a web app, we prob. don’t even need to restart the server. Just pop up the OSGi console, disable the old plugins and enable the new ones. Fascinating!
1. In this section, I am going to talk about why I chose RAP to implement CodeFaces and my experience of using RAP. 2. First take a look at this requirement, there are four key terms here: an IDE way, explore codes, multiple source control systems, and browser. 3. One of the keys to make this app a success, we can also call it “the domain”, is its ability to adapt to multiple source control systems. We need a framework that can facilitate us to implement such extensibility. 4. extensible system a really common OSGi pattern. It means the ability to add/remove implementations in a system. For example, you can make a menu extensible so that people can contribute menu items to it; Another example is Eclipse, take Mylyn as an example, probably some of you have heard of or are using Mylyn, it has extension points on the issue tracking system connectors, such as Jira or Bugzilla, to its task management UI. 5. Back to CodeFaces, this domain requires us to have the flexibility to extend its functions to multiple source control systems. That’s why we chose OSGi and Equinox.
0. Let’s walk through an example on how to gradually refactor to an extension point. We will take building the scm connector for CodeFaces as an example. I am not sure if anyone is already familiar with building extension points? You specify some input/output in the extension schema, fill in the extensions content in the plugin.xml, and use the Equinox APIs to get back the extension points information. You can achieve highly decoupled system in the end because the control is inverted. I will explain more. 1. The key is to implement the extension points in small steps. Don’t rush to come up with an extension points from the beginning. You may end up with an extension point that is not generic enough for all the extensions. 2. Extension point can exist in places with a strategy pattern. For example, we have different strategies (different algorithms) of SCMConnector in this example, github or subversion. 3. For the first strategy implementation, just leave the strategy in the code. At this point, you should only care about this strategy implementation and try to make the whole system work. Building up the UI, building the backend. You ain’t gonna need an extension point at this point. 4. After you finish building up everything around your first strategy. Then you start to think about the 2nd strategy, for instance, I want a 2nd strategy called subversion connector. Adjust the strategy interface if necessary, build a factory to create this strategy and refer to it by an ID, in this case, the GitHubConnector is referred by its ID “GitHub”. 5. Next you can go ahead and build up the extension point schema, in this example, we know that the input is the connector ID and the output is a SCMConnector implementation. We specify those in the schema. Then we put the extensions in the plugin.xml. In the factory implementation, we read the extension point implementations by using Equinox’s APIs. We instantiate classes as necessary. 6. The last step, and many people may forget about this step, is to refactor the extension implementations out to a new project. Because the strategy implementation is referred by ID, which is a string, in other words, implementations are being pushed to the host, instead of the host is pulling implementations. You are referring classes by an ID. This is very similar to Spring. The host doesn’t refer to any specific implementation of the strategy anymore. The control is inverted. In OSGi world, extensions is an implementation of the inversion of control pattern. And it’s more flexible, you have full control of the creation lifecycle.
1. RAP is not bug free, I fired two bugs when I was using it 2. Building....we built an widget that can make cross domain ajax call, since GitHub has API call limit per IP, we put this limit to the client side 3. Documentations is incomplete for some parts, I spend a lot of time on figuring the CSS for theming.
Keys: small steps, no rush to make it an extension point upfront, gradually
Identify your extension points (code smell), for example exists in places with a strategy pattern.
For the first implementation, leave your strategy in the code (YAGNAEP): SCMConnector connector = new GitHubConnector();
At some point, you realize you need a second strategy, adjust the interface if necessary, create a factory, refer to the strategy by a String, e.g., an ID: SCMConnector connector = SCMConnectorFactory.create(“GitHub”); SCMConnector connector = SCMConnectorFactory.create(“Subversion”);
Build up the extension point schema, put extensions in plugin.xml, and in the factory, use Platform.getExtensionRegistry() to read extension point implementations.
Refactor the extensions out to a new project if necessary. Control is already inverted. Highly decoupled system is achieved! org.codefaces.core org.codefaces.core.github org.codefaces.core.subversion