Tuesday, May 22, 2018

OSGi R7 Highlights: The Http Whiteboard Service

The OSGi Compendium Release 7 specification contains version 1.1 of the Http Whiteboard specification which includes a number of new features.

Before we dive into the new features, let's start with a summary of what the Http Whiteboard Specification is about: It provides a light and convenient way of using servlets, servlet filters, listeners and web resources in an OSGi environment through the use of the Whiteboard Pattern. The specification supports registration of the above-mentioned web entities and grouping them together in context. A three-part introduction into the Release 6 version of the Http Whiteboard can be found here, here and here.

Component Property Types


Registering web entities using the Http Whiteboard usually requires specifying several service registration properties. In Release 7, Declarative Services added the ability to use component property types to annotate components and set property values in a type-safe manner. A set of annotations has been added to the Http Whiteboard specification to make use of this new feature in Declarative Services, simplifying the development of such web entities.

For example, registering a servlet at the path /game looks now like this:
@Component(service = Servlet.class)
@HttpWhiteboardServletPattern("/game")
public class MyServlet extends HttpServlet {
  ...
}

Similarly, defining additional service properties can easily be done by adding more annotations to the class. In the following example, we declare the servlet to support asynchronous processing and mount the servlet in a specific Http Context (in contrast to using the default context as above):
@Component(service = Servlet.class)
@HttpWhiteboardServletPattern("/game")
@HttpWhiteboardContextSelect("(" 
  + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME
  + "=mycontext)")
@HttpWhiteboardServletAsyncSupported
public class MyServlet extends HttpServlet {
  ...
}

Further annotations have been added to simplify the development of servlet filters, resources, listeners error pages, and servlet context. A full list of these can be found here.

Multipart File Upload


Support for multipart file upload handling and configuring this handling has been added. The possibilities are the same as supported by the servlet specification. The multipart handling can be enabled for a servlet by specifying additional service registration properties. Again, using a component property types simplifies the specification of the required properties. In the following example we enable multipart file upload for the servlet and restrict the size of the uploaded files to 500,000 bytes:
@Component(service = Servlet.class)
@HttpWhiteboardServletPattern("/game")
@HttpWhiteboardServletMultipart(maxFileSize=500000)
public class UploadServlet extends HttpServlet {
  ...
}

The chapter about Multipart File Upload contains a complete description of the service properties for multipart file upload.

Pre-Filtering


A servlet filter is registered with an Http Context together with some rules when the filter is applied, e.g., by specifying a path pattern or a servlet name. However, servlet filters are run after a potential user authentication and therefore never get run when this authentication fails. In addition, these filters are only run if the request is targeting an existing endpoint, either a servlet or a resource.

On the other hand, some use cases require running some code with every request or before authentication. For example, logging all requests, regardless of whether authentication is successful is one of those use cases. Preparing the request by adding additional information from a third party system might be another one.

With the updated Http Whiteboard specification, a new web entity, the Preprocessor has been added. All services registered with this interface are invoked before request dispatching or authentication is performed. Therefore such a preprocessor will receive all requests. The Preprocessor interface is just an extension of the servlet filter interface and just acts as a marker to distinguish a preprocessor from a normal servlet filter. The following example implements a simple preprocessor, logging all requests:
@Component(service = Preprocessor.class)
public class LoggingFilter implements Preprocessor {

  public void doFilter(ServletRequest request,
                       ServletResponse response,
                       FilterChain chain)
  throws IOException, ServletException {
    System.out.println("New request to "
      + ((HttpServletRequest)request).getRequestURI());
    chain.doFilter(request, response);
  }

  public void init(FilterConfig filterConfig)
  throws ServletException {
    // initialize the preprocessor
  }

  public void destroy() {
    // clean up
  }
}

As a preprocessor is invoked for every request, there are no special service properties for this type of service, especially this service is not associated with any Http Context as the dispatching to a context happens after the preprocessors are invoked.

Updated Security Handling


Security handling or authentication can be implemented by registering your own implementation of the ServletContextHelper service and implementing the handleSecurity method. Web entities like servlets or filters can then be associated with this context ensuring that they are only invoked if the authentication is successful.

While the handleSecurity methods provide a good mechanism to check for authentication and potentially add additional information to the current request like a user context which can then be used by the web components, a method for cleaning up such state was missing. With the update of the Http Whiteboard, a new method finishSecurity has been added which is now closing this gap. This new method is the counterpart of handleSecurity and is invoked when the request processing is done. By implementing this method any resources allocated through handleSecurity can be cleaned up.

More on the Http Whiteboard Update


This blog post mentions only those new features which I think are the most important ones of the new version 1.1. You can find the full list of changes at the end of the Http Whiteboard specification.


Want to find out more about OSGi R7?

This is one post in a series of 12 focused on OSGi R7 Highlights.  Previous posts are:
  1. Proposed Final Draft Now Available
  2. Java 9 Support
  3. Declarative Services
  4. The JAX-RS Whiteboard
  5. The Converter
  6. Cluster Information
  7. Transaction Control
Be sure to follow us on Twitter or LinkedIn or subscribe to our Blog feed to find out when it's available.

Thursday, May 17, 2018

OSGi Community Event 2018 - CFP Now Open

We are pleased to announce the OSGi Community Event 2018 and that the Call For Papers (CFP) for this year's conference is open.

The OSGi Community Event 2018 is returning to Ludwigsburg in Germany where we are pleased to be co-located with EclipseCon Europe again.  The event will take place October 23-25 inclusive and will feature an OSGi tutorial, talks, a BOF and other OSGi community-related activities.

Attendees will have access to the full program at the OSGi Community Event and EclipseCon Europe.


CALL FOR PAPERS IS OPEN

We are looking for one, 3-hour tutorial and many more 35-minute standard talks. The Call for Papers (CFP) is open to anyone who has an experience, expertise or story to share about OSGi technology or the OSGi ecosystem. We are particularly interested in use cases and new initiatives around OSGi in enterprise, embedded, Cloud, Telco, and IoT.

The Call For Papers for this year's event is open now and closes 16 July.

If you fancy a chance to win a €50 Amazon voucher, then get your submission in by 2 July and you will be considered for the Early Bird pick where the winner will receive the voucher.

You can find out further details and information on how to submit a talk or tutorial on our conference website.

There you can also find links to speaker and submission FAQs that EclipseCon has put together.

If you have any questions about submissions or the conference in general, then please contact us.

We are looking forward to reading your talk and tutorial submissions and also seeing the OSGi Community in Ludwigsburg in October.

Tuesday, May 8, 2018

OSGi R7 Highlights: Transaction Control

The OSGi R7 specification contains a wide variety of exciting new features covering a wide variety of different use cases. The OSGi Transaction Control service is one of these new specifications providing modularity for transactional resource management.

A New Take on an Old Problem


Transactions have been used in software for decades, and over time they have become simpler to use. The Java Transaction API provides a common API for transaction management in Java, but this is still considered too hard to use directly. Java EE and the Spring framework, therefore, created a variety of declarative models. Before we talk about the new OSGi Transaction Control service we should understand how to work (or not) with these technologies.

Working with Declarative Transactions


The recommended approach for using transactions in Java EE and Spring is to apply the @Transactional annotation to your transactional methods.
public class TransactionalBean {

  DataSource ds;

  @Transactional
  public void addUser(String user) throws SQLException {
    // Add the user
    try (Connection conn = ds.getConnection();
         Statement s = conn.createStatement(
                 "insert into users values(?)")) {
      s.setString(1, user);
      s.executeUpdate();
    }
  }
}

This solution is incredibly simple, unfortunately, it is also deceptively so. Rather than the explicit complexity of managing your own transactions all of the complexity is hidden behind the @Transactional annotation. Unfortunately, hiding complexity doesn't make it go away, it just leads to other questions.
  • How did the transaction actually start and stop?
  • How did the database connection know to participate in the transaction?
  • What will cause the transaction to roll back?

Answering the Questions 


It turns out that there are a lot of moving parts behind the curtain!

Firstly, the transaction is started and stopped by container code running immediately before and after your method runs. This is almost always achieved by creating a proxy for a managed instance and ensuring that all access to the instance is through the proxy. Unfortunately, it's pretty easy to violate that restriction:
public class TransactionalBean {

  ...

  @Transactional(SUPPORTED)
  public void addIfNecessary(String user) {
    if(!userExists(user) {
      addUser(user);
    }
  }
}

In this case, we have another method on our object which can run without a transaction. When this method makes a call to the addUser method it does not touch the proxy. As a result, we can end up running the addUser method outside a transaction.

Secondly, the data source is enlisted because it is also proxied - when the getConnection call is made it locates the current transaction and enlists the connection with that transaction. Importantly this only works if the same person is doing all the proxying and uses the correct transaction manager.

Thirdly, a Java EE (or Spring) transaction will roll back if the method completes with an unexpected exception. Checked exceptions are part of the method signature and therefore not considered to be unexpected. This means that the SQLException in our example does not trigger a rollback

The biggest problem with proxying is that you need to have an all-knowing container ready, running and responsible for managing the objects and resources in the system. In Java EE this is the Application Server, in Spring it is the Application Context, but in OSGi? One thing that we learn over and over is that for a system to be modular you cannot have a single global container. The provider of the resources and the provider of the business objects must be free to use whatever frameworks they choose. We also learn that for a system to be robust we cannot rely on other modules to start before we do. Proxying to provide transactions is, therefore, a fundamentally flawed approach in OSGi.

Transaction Control - A Modular Approach


The OSGi Transaction Control service is a new specification which is designed to address the issues with the Java EE/Spring transaction management model.

One of the biggest differences when using Transaction Control is that transaction management is programmatic, not declarative, and uses a functional decorator pattern. This means that there is no need for a proxy to introduce transaction management instructions into your code, and the transaction is guaranteed to start however your method gets called.
@Component
public class TransactionalComponent {

  @Reference
  TransactionControl txControl

  public void addUser(String user) throws SQLException {
    // Add the user
    txControl.required(() -> {
        // This scoped work runs in a transaction
        return 42;
    });
  }
}

The Transaction Control service offers convenient methods for:

  • Requiring a transaction
  • Requiring a new transaction
  • Suspending a transaction
  • Checking to see whether a transaction is active or not

Completing the Transaction


The transaction and all other state associated with the scope is completed when the scoped work returns. Normally the work will return a value, and this value will be returned by the required method (the integer 42 in the example above). Returning a normal value will cause the transaction to be committed. If the commit fails then the Transaction Control service will throw a TransactionException from the required method.

Rolling Back 


One other important difference between Java EE/Spring transactions and the Transaction Control Service is that in Transaction Control every Exception triggers rollback by default. This is much more likely to give the correct behavior when things go wrong.

The easiest way to get a rollback is, therefore, to throw an exception from your scoped work! If your scoped work does complete with an exception then this will be wrapped in a ScopedWorkException and re-thrown by the required method. Sometimes, however, you don't want to commit your work, but it isn't an exceptional circumstance. In this case throwing an exception is the wrong thing to do, instead, you should simply mark the transaction for rollback.

@Component
public class TransactionalComponent {

  @Reference
  TransactionControl txControl

  public void addUser(String user) throws SQLException {
    // Add the user
    txControl.required(() -> {
        // This transaction must roll back
        txControl.setRollbackOnly();
        return 42;
    });
  }
}


A full description of the scope lifecycle is available in the Transaction Control specification.

Scoped Resources


In order for a transaction to be useful, it must have one or more resources participating in it. In Java EE and Spring these resources must be managed by the container so that they can be enlisted. The Transaction Control specification changes this model to let the OSGi bundle take control of enlistment.

Scoped Resources are created from a ResourceProvider, an object which is either found in the service registry or created by a factory service. The ResourceProvider interface is generic and usually subclassed to provide a specific resource type. The Transaction Control specification includes standard interfaces for creating scoped JDBC Connection objects and JPA EntityManager instances.

The easiest way to get a resource provider instance is to configure the resource provider implementation. For example, the Reference Implementation from Apache Aries can be configured as follows (using the configurator JSON format)
{
    // Global Settings
    ":configurator:resource-version" : 1,
    ":configurator:symbolic-name" : "org.osgi.blog.tx.config",
    ":configurator:version" : "0.0.1.SNAPSHOT",
    
    
    // Configure a JDBC resource provider
    "org.apache.aries.tx.control.jdbc.xa~resource": {
           "osgi.jdbc.driver.class": "org.h2.Driver",
           "url": "jdbc:h2:./data/database" }
}

The configured JDBCConnectionProvider can then be combined with a Transaction Control Service to create a scoped resource and used as follows:

@Component
public class TransactionalComponent {

  private final TransactionControl txControl;

  private final Connection txConnection;

  @Activate
  public TransactionalComponent(
      @Reference TransactionControl txControl,
      @Reference JDBCConnectionProvider provider) {
    this.txControl = txControl;
    this.txConnection = provider.getResource(txControl);
  }

  public void addUser(String user) throws SQLException {
    // Add the user
    txControl.required(() -> {
      Statement s = txConnection.createStatement(
             "insert into users values(?)");
      s.setString(1, user);
      return s.executeUpdate();
    });
  }
}

Resource Lifecycle


You may have noticed that the example using Transaction Control never closes its connection or the Statement it creates. In fact, the same connection instance is used for every call to addUser! This isn't a mistake but in fact, the recommended way to make use of a scoped resource. When you call getResource on a resource provider you aren't being given a physical resource, but a transaction-aware resource object.

The first time that you call the scoped resource object inside a piece of scoped work it does several things:

  • It obtains a real physical resource from an underlying pool
  • It enlists the physical resource in the transaction (if there is one)
  • It registers the physical resource with the ongoing transaction context so the same physical resource is used for the rest of the scoped work
  • It registers a completion callback so that the physical resource can be automatically returned to the pool
All of this means that you never need to worry about getting a different connection instance, or about closing it when you're done. All resource access is implicitly and automatically bounded by the scoped work, this includes the objects created by the scoped work such as Statements and ResultSets.

In Summary


The Transaction Control Service provides a simple, reliable, modular solution for transaction lifecycle management and resource access. If you're interested in seeing more usage of Transaction Control then you should check out the data access services from the OSGi enRoute for R7 microservice example.



Want to find out more about OSGi R7?

This is one post in a series of 12 focused on OSGi R7 Highlights.  Previous posts are:
  1. Proposed Final Draft Now Available
  2. Java 9 Support
  3. Declarative Services
  4. The JAX-RS Whiteboard
  5. The Converter
  6. Cluster Information
Be sure to follow us on Twitter or LinkedIn or subscribe to our Blog feed to find out when it's available.