Thursday, November 1, 2012

Fun at Java One in San Francisco and after

Beside having fun in San Francisco, I've presented at Java One with my more experienced colleague Mitesh Meswani! Recording of our BOF2737 "Developing Multitenant Applications with HK2 2.0 and EclipseLink" session is available here, see Media on right pane.

It was my first talk, and it went quite smoothly, due to small audience :) But the number (20) matched our expectations! HK2 is definitely not so known and sexy, as HTML5, NoSQL and Scala. But we've got something to go on.

Looks like there is no much demand for sharing run-time between tenants. However data isolation draws big interest, so including EclipseLink, was useful for the audience.

From other hand many people think of multi-tenancy in the same way - running single instance of the application for multiple clients. That's great! And everybody tries it differently.

It's worth to mention IBM's CON6465 - JVM Support for Multitenant Applications
talk about multi-tenant JVM. But beside IBM there is Waratek that does very good job in context of multi-tenancy in JVM too, but I have not seen their session, if there was any. And there might be more of course.

Other, not related to multi-tenancy but to CDI, CON7780 - Designing Java EE Applications in the Age of CDI, draw my interest. And caused to check that it's also possible to @Inject Logger with HK2! See my git commit#4dcad7b6e3 for example!. However, it brought rather difficult problem, multi-tenant logging. Well, there are much more problems like this, of course.

Also, I liked Venkat Subramaniam the most! And again, his CON3454 - Concurrency Without Pain in Pure Java makes me to highlight that HK2 also provides STM without pain in even more pure Java. In order to change any configuration element, one must start a configuration transaction that ensures restricted access to the configuration. The following demonstrates transaction invocation for mutating injected configuration object:

@Inject
HttpListener httpListener;

ConfigSupport.apply(new SingleCodeCode<HttpListener>() {
        public Object run(HttpListener wListener) {
                wListener.setPort("8080");
        }, httpListener);


Hopefully there will be something more, stay tuned!

Friday, August 10, 2012

Multi-Tenant Programming Model

This time, as promised, I'd like to describe one of a few possible models of developing Multi-Tenant applications, with HK2 and EclipseLink.

Disclaimer: HK2 and EclipseLink don't have to be used together. This model is not intended for any PaaS. And this post does not cover all aspects of developing multi-tenant applications. This model attempts to simplify programmer experience when developing multi-tenant application with single application instance per tenant approach.

Let me start with less familiar HK2 first. It is an implementation of the JSR 330: Dependency Injection standard for Java.  I won't repeat it's documentation, but highlight its configuration subsystem. HK2 offers support for software configuration in xml file. E.g. you can have pure class with few annotations:

@Configured
public interface HttpServer extends ConfigBeanProxy {
    @Attribute
    String getName();
    void setName(String name);
}

Then it is mapped to xml:
<http-server name="..." />

It is similar to JAXB, without explicit binding, or rather with binding by convention, and with restricted write access. Finally, with HK2, consumer may have configuration injected:

@Service
public class Foo {
    @Inject
    HttpServer httpServer;
}

See my previous post for how to start with HK2 support for xml configuration.

Recent version 2.2 of HK2 among other things, introduces @Proxiable annotation. Combined with custom @Scope-d annotation, and applied to configuration object, it allows to have once injected configuration be different at execution time depending on the state of the system. So configuration may be different for Alice and Bob, tenants of your application.

See Tenant Managed Scope Example for details on how to implement that @TenantScoped trick. And try it yourself, check out examples/ctm@hk2.java.net.

From other hand, hopefully better known, EclipseLink is implementation of Java persistence standard. Version 2.4 (Juno) brings better support for Multi-Tenancy. Beside Documentation and Examples I would like to recommend full-stack MySports example, provided by EclipseLink team also. Shortly, EclipseLink allows to impelement persistence with table per tenant or single table, using column discriminator and gives few architectural options:
  • Dedicated Persistence Unit - separate persistence-unit in persistence.xml, so application must request the correct PersistenceContext or PersistenceUnit for tenant.
  • Persistence Context per Tenant - single persistence unit definition in the persistence.xml and a shared persistence unit (EntityManagerFactory and cache).
  • Persistence Unit per Tenant - single persistence unit defined in the persistence.xml and different persistence contexts with their own caches are created per tenant.

And now, applying @TenantScoped @Proxiable @Scope from HK2 example above to one of the EclipseLink multi-tenant architecture, HK2 will substitute persistence context for tenenat at runtime, like this:

public class TenantEntityManagerFactory implements Factory<entitymanager> {
    @Inject
    private TenantManager manager;

    ...

    @TenantScoped
    public EntityManager provide() {

        String currentTenant = manager.getCurrentTenant();
        Map properties = new HashMap();
        properties.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT,
                 currentTenant);
        properties.put(PersistenceUnitProperties.SESSION_NAME, currentTenant);
        EntityManager em = Persistence.createEntityManagerFactory("multi-tenant-pu",
                 properties).createEntityManager();
        return em;
    }
}

So consuming code can have EntityManager provided once by HK2 dependency injection, and have it different depending on current tenant, thread safe! E.g.

public class Foo {
    @Inject
    EntityManager entityManager;

    public void testPersistence() {
        // assume tenantManager.setCurrentTenant() is called somewhere in stack

        entityManager.getTransaction().begin();
        Customer customer = new Customer();
        customer.setName("ACME");
        entityManager.persist(customer);
        entityManager.getTransaction().commit(); 
    }
}

See my eclipselink-hk2@github for working example. It also demonstrates  usage of Extensible Entities.

That's it. Let me know if you try this model.

Monday, August 6, 2012

Quick TIP: View diff attached to JIRA issue

I often like to see diff attached to a JIRA issue, but if you click attachment link, browser usually suggests to download attachment. Though if you right-click the link, copy link location and then paste into browser address bar and prefix it with view-source: it will simply display it, e.g. (copy & paste it into browser address bar):

view-source:http://java.net/jira/secure/attachment/50568/working.diff

Diff taken from http://java.net/jira/browse/HK2-63

Convenient, isn't it?

Tuesday, July 24, 2012

About SaaS

This time I'd like to share my views about different approaches to SaaS. Remember from my previous post - SaaS (just) scales on demand, and when executed, it is somehow isolated from other tenants of the "same" software.

1) PaaS Ready, i.e. software that is ready to be installed/deployed to PaaS. This can be for example a Ruby on Rails application ready to be deployed to Heroku, or java web application to be deployed to Jelastic. It means Software Instance per tenant. E.g. origin code can be hosted on GitHub, you clone it, customize and deploy to PaaS. This is not much different from classic hosting. Beside the fact that it will scale!

Oh, I should have mentioned the simplest approach, used at some of existing SaaS marketplaces. A SaaS markeplace company lets you use a software without being bothered with its installing and deploying. It does not necessarily need to be SaaS actually. I think this is very close to Amazon Marketplace, when they sell pre-configured Amozon Machine Images (AMI). Interesting, but something different. Or non-SaaS approach to SaaS :)

2) Business SaaS, let's call it. SalesForce, WSO2 and may be many others, allows to build SaaS at their platform online. WSO2 has somewhat better case, when one can deploy special type of application - carbon application, but you still need to configure resources needed for the application, like database or web services. Well, how is it different from the first case? At Heroku or Jelastic you may also need to setup resources needed for the application. Is it different because SalesForce and WSO2 applications share execution environment? In my thoughts, difference is rather that you don't have standalone codebase that you can just deploy into PaaS, you build your software with their online tools.

Well, with WSO2 it's not so bad (from software developer point of view, of course). Developers create carbon applications "offline".  Also, what's interesting, setting carbon.enable.saas=true in web.xml, WSO2 application becomes multi-tenant. But looks like WSO2 tenant context can not be leveraged in the application. Developer still needs  to have a multi-tenant architecture for his application, like multi-tenant data store , or anything else. Also it's not clear if only super tenant can run saas enabled carbon application.

Note, I was trying hard to understand whether SalesForce allows to create multi-tenant application. Looks like not. Also it does not seem possible to deploy any redistributable package.

3) Multi-tenant SaaS - tenant aware application, such that each tenant will share the instance of running software. It may look the same for tenants, but technically it will be one deployed instance, serving needs of different tenants. Isolation happens on application level, similarly to WSO2 all resources are shared, but everything is executed isolated. Why it's needed? For better resource utilization. Notice, it comes from previous case. It also can be PaaS Ready application.

Well, the latter is actually area of my research, for those curious why I'm thinking so much about cloud computing. Hopefully next post(s) will be about programming model(s) of multi-tenant applications in Java. Though don't expect it to be "ready" for any PaaS yet.

Off-topic, it could be interesting to talk about sharing revenue between PaaS provider developer of SaaS. It's clearly possible in non-SaaS case, like being an AMI vendor. It's also likely possible in second type. And it's completely up to software developer in third case.

In 2nd case, it rather depends on how billing works in WSO2-like saas enabled case. Will tenant be billed for using super-tenant resources, and/or will he have his own resources?

I'm rather inclined to 3rd type, multi-tenant SaaS, which leaves revenue sharing out :) And hope to write about it. Is there someone excited?

And picture!




Thursday, July 5, 2012

About Cloud Computing

Let me express my understanding of (computing) cloud, that is so much and long talked about. I've come to this understanding today, while talking to my wife - she's great listener of my thoughts like this. Well, I like to explain things to her. I understand them better then :)

First, as to me, the term (computing) cloud, is over used. Mostly everybody uses it for mostly every internet service. That is not absolutely wrong. Because cloud picture is widely and long used to depict internet. Ok, but modern (computing) cloud, must be something else.

Second, (computing) cloud exists on different (3) levels, Infrastructure, Platform and Softwre, all used as  a Service. Iaas, PaaS and Saas for short. What it means?

I think Amazon if not the first, but definitely is the most noticeable provider of IaaS with their Elastic Computing Cloud (EC2). I base on them my understanding. I guess the main "cloudy" thing of their service is elasticity. So, I take it as base. Computing cloud on infrastructure level gives its users feeling of endless computing capacities, by number of smaller computer joined together, in cluster, like into cloud. You get virtually computer. And you can get possible more of them, on demand, interconnected. That's cloud on infrastructure level. That's IaaS.

Further, Platform as a Service, or cloud platform, must be something very similar. Instead of computer, you get application platform. Like Heroku. You can not any longer do everything what you could do on your own computer. Instead you get very strict rules, or predefined environment, or set of them. You can only host your (web) application, written in limited number of programming languages, using limited number of development frameworks and also limited access to peripheral devices. Like you may not be allowed to write on disk or open sockets. But what you get? Virtually endless horizontal extensibility. You app can serve as many requests per second as you would like to pay, but without any efforts to scale. Increase your computing power and cloud platform will do the rest for you. It will copy your application(s) to new computers and balance load between them. That's PaaS.

Finally, SaaS. That was most tricky for me. And I've tired once already to think about it in context of multi-tenancy. So, now, looking from bottom up, I think, it must be more clear what differs Software as a Service from software/web service. As to me, software should use term 'cloud' if and only if it allows you to serve your users needs, not yours. Imagine, you get virtually e-shop, and your friend uses the same e-shop software service. But you both have your own end-user interface, your own products and your own customers. And what's important, when you get more customers, you ask your e-shop software service provider to increase computing power, and that's all you need to grow. So, at Software level, you can not develop your own applicaiton, but you can use what's offered for your business. Some other example - online surveys solutions. Think about it.

Cloud software on Cloud platform in (computing) Cloud - 4Cast?


Sunday, May 6, 2012

MapReduce & CouchDB

Just a rhetoric post.

Some time ago seeking of more information about NoSQL, I've come across Apache CouchDB, and found it more interesting for myself than MongoDB.

First, I felt a lack of permission settings for read operation, see answered question on Stack Overflow. But I went further, and created simple TODO list, and later more useful, but still simple notebook - Li.Couch, just to get more experience in NoSQL and Knockout, oh, and to use it for myself also.

Now, I met closely MapReduce, trying to implement simple search for the notebook. But I felt lack of better implementation of Reduce in CouchDB. "A common mistake new CouchDB users make is attempting to construct complex aggregate values with a reduce function. Full reductions should result in a scalar value, like 5, and not, for instance, a JSON hash with a set of unique keys and the count of each" [CouchDB The Definitive Guide: Finding Your Data with Views]. And I made this mistake.

I can't find "original" idea of MapReduce from Google, but if WikiPedia can be considered as source of the truth, reduce part of MapReduce is not limited to scalar result: MapReduce.

I also found very nice paper Experiments with MapReduce in Erlang, that demonstrates what I would like to have in CouchDB:

map: (K1, V1) → List[(K2, V2)] reduce: (K2, List[V2]) → List[V2] mapreduce: (List[(K1, V1)],map,reduce) → Map[K2, List[V2]] 
Why CouchDB does not allow to emit data in reduce function similarly to map to obtain reduced list?

Sunday, April 22, 2012

Multi Tenancy

I've spent some time on thinking about multi-tenancy and clarified some thing for myself.

I can see three types of multi-tenant applications:

  1. Like email or todo lists for more simplicity. Running same code base for different users, keeping all data of a multi-tenant application in a single database

    To avoid unnecessary repetition of a query criterium that selects only data for the current user. Here EclipseLink with VPD or Hibernate Filters can be used.

    Note, such multi tenant application may also be served on separate (virtual) host for each tenant, such as http://firsttenant.yourapp.com and http://secondtenant.yourapp.com.
     
  2. More complicated case, e.g. multi-store e-commerce platform - runs once, but serves different stores and is manged by different owners, all isolated. Known as OnDemand.

    Caution, such solutions can be implemented as non multi-tenant application, but as running on separate  (virtual) machines/hosts, however with the same code base.  Although, supertmarket/marketplace (buy/sell e-commerce) is not a multi-tenant app at all.
     
  3. Multi-tenant platform, e.g. salesforce.com - platform for developing business applications in multi-tenant environment, e.g. ERRP with multiple departments as tenants. Their multi tenant architecture -  http://wiki.developerforce.com/page/Multi_Tenant_Architecture - Pivot tables, object oriented immutable db schema - OrgId, UserId - FieldId, Values.
Where you are? :)

Let me know your comments.

And if anybody interested I may post more  details about some technical approaches for developing multi-tenant applications.

Monday, February 27, 2012

Update for hello-world-hk2-sample

Take a look at Sahoo's hello-world-hk2-sample part I, updated for hk2 version 1.6.30.

I also extended it with support for Configuration, which is another very interesting part of HK2.

You can find sources at GitHub.

Important points to notice:

1) DomainXml as starting point for configuration. Mainly it is Populator, so with help of ConfigParser.parse it populates habitat with hk2 configuration beans habitants.

2) Named configuration beans:

Domain extends ... Named, so that it can be looked up by name, e.g.

@Inject(name="test")
Domain domain;
or
habitat.getComponent(Domain.class, "test2");
3) And Transactions support (modifiable configuration), for which it's necessary to override DomDocument.make() method to produce ConfigBean objects instead of Dom.

public class MyDocument extends DomDocument<configbean> {
    public MyDocument(final Habitat habitat) {
        super(habitat);
    }
    
    @Override
    public ConfigBean make(final Habitat habitat, XMLStreamReader xmlStreamReader,
            ConfigBean dom, ConfigModel configModel) {
        // by default, people get the translated view.
        return new ConfigBean(habitat,this, dom, configModel, xmlStreamReader);
    }

}

Then use it in DomainXml.run() method for ConfigParser:

parser.parse(res, new MyDocument(habitat));

That's all so far, but it may be updated for persisting configuration modifications.