From seam-commits at lists.jboss.org Thu May 28 22:29:28 2009 Content-Type: multipart/mixed; boundary="===============2453669456139245971==" MIME-Version: 1.0 From: seam-commits at lists.jboss.org To: seam-commits at lists.jboss.org Subject: [seam-commits] Seam SVN: r11028 - branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US. Date: Thu, 28 May 2009 22:17:32 -0400 Message-ID: --===============2453669456139245971== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Author: dan.j.allen Date: 2009-05-28 22:17:32 -0400 (Thu, 28 May 2009) New Revision: 11028 Added: branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US/ClusteringAnd= EJBPassivation.xml Modified: branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US/master.xml Log: JBSEAM-3425 Added: branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US/Clusterin= gAndEJBPassivation.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US/ClusteringAn= dEJBPassivation.xml (rev 0) +++ branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US/ClusteringAn= dEJBPassivation.xml 2009-05-29 02:17:32 UTC (rev 11028) @@ -0,0 +1,424 @@ + + + + Clustering and EJB Passivation + + + Please note that this chapter is still being reviewed. T= read carefully. + + + + This chapter covers two distinct topics that happen share a common= solution in Seam, (web) clustering and EJB + passivation. Therefore, they are addressed together in this refere= nce manual. Although performance tends to be + grouped in this category as well, it's kept separate because the f= ocus of this chapter is on the programming + model and how it's affected by the use of the aforementioned featu= res. + + + + In this chapter you will learn how Seam manages the passivation of= Seam components and entity instances, how to + activate this feature, and how this feature is related to clusteri= ng. You will also learn how to deploy a Seam + application into a cluster and verify that HTTP session replicatio= n is working properly. Let's start with a + little background on clustering and see an example of how you depl= oy a Seam application to a JBoss AS cluster. + + + + Clustering + + + Clustering (more formally web clustering) allows an applicatio= n to run on two or more parallel servers + (i.e., nodes) while providing a uniform view of the applicatio= n to clients. Load is distributed across the + servers in such a way that if one or more of the servers fails= , the application is still accessible via any + of the surviving nodes. This topology is crucial for building = scalable enterprise applications as + performance and availability can be improved simply by adding = nodes. But it brings up an important question. + What happens to the state that was on the server tha= t failed? + + = + + Since day one, Seam has always provided support for stateful ap= plications running in a cluster. Up to this + point, you have learned that Seam provides state management in = the form of additional scopes and by governing + the life cycle of stateful (scoped) components. But state manag= ement in Seam goes beyond creating, storing + and destroying instances. Seam tracks changes to JavaBean compo= nents and stores the changes at strategic + points during the request so that the changes can be restored w= hen the request shifts to a secondary node in + the cluster. Fortunately, monitoring and replication of statefu= l EJB components is already handled by the EJB + server, so this feature of Seam is intended to put stateful Jav= aBeans on par with their EJB cohorts. + + + + But wait, there's more! Seam also offers an incredibly unique = feature for clustered applications. In + addition to monitoring JavaBean components, Seam ensures that = managed entity instances (i.e. JPA and + Hibernate entities) don't become detatched during replication.= Seam keeps a record of the entities that are + loaded and automatically loads them on the secondary node. You= must, however, be using a Seam-managed + persistence context to get this feature. More in depth informa= tion about this feature is provided in the + second half of this chapter. + + + + Now that you understand what features Seam offers to support a= clustered environment, let's look at how you + program for clustering. + + + + Programming for clustering + + Any session- or conversation-scoped mutable JavaBean compo= nent that will be used in a clustered + environment must implement the Mutable = interface from the Seam API. As part of the + contract, the component must maintain a dirty flag that is= reported and reset by the + clearDirty() method. Seam calls this me= thod to determine if it is necessary to + replicate the component. This avoids having to use the mor= e cumbersome Servlet API to add and remove the + session attribute on every change of the object. + + + You also must ensure that all session- and conversation-sco= ped JavaBean components are Serializable. + Additional, all fields of a stateful component (EJB or Java= Bean) must Serializable unless the field is + marked transient or set to null in a @PrePassivate= method. You can restore the value + of a transient or nullified field in a @PostActiva= te method. + + + One area where people often get bitten is by using List.subList to create a list. The + resulting list is not Serializable. So watch out for situat= ions like that. If hit a + java.io.NotSerializableException and can= not locate the culprit at first glance, you + can put a breakpoint on this exception, run the application= server in debug mode and attach a debugger + (such as Eclipse) to see what deserialization is choking on. + + + + Please note that clustering does not work with hot dep= loyable compoennts. But then again, you shouldn't + be using hot deployable components in a non-developmen= t environment anyway. + + + + + + Deploying a Seam application to a JBoss AS cluster with= session replication + + + The procedure outlined in this tutorial has been validated= with an seam-gen application and the Seam + booking example. + + + + In the tutorial, I assume that the IP addresses of the mas= ter and slave servers are 192.168.1.2 and + 192.168.1.3, respectively. I am intentionally not using th= e mod_jk load balancer so that it's easier to + validate that both nodes are responding to requests and ca= n share sessions. + + + + I'm using the farm deployment method in these instructions= , though you could also deploy the application + normally and allow the two servers to negotiate a master/s= lave relationship based on startup order. + + + + + JBoss AS clustering relies on UDP multicasting provide= d by jGroups. The SELinux configuration that + ships with RHEL/Fedora blocks these packets by default= . You can allow them to pass by modifying the + iptables rules (as root). The following commands apply= to an IP address that matches 192.168.1.x. + + /sbin/iptables -I RH-Firewall-1-INPUT 5 -p= udp -d 224.0.0.0/4 -j ACCEPT +/sbin/iptables -I RH-Firewall-1-INPUT 9 -p udp -s 192.168.1.0/24 -j ACCEPT +/sbin/iptables -I RH-Firewall-1-INPUT 10 -p tcp -s 192.168.1.0/24 -j ACCEPT +/etc/init.d/iptables save + Detailed information can be found on this page on the JBos= s Wiki. + + + + + Create two instances of JBoss AS (just extract t= he zip twice) + + + Deploy the JDBC driver to server/all/lib/ on bot= h instances if not using HSQLDB + + + Add <distributable/> as th= e first child element in WEB-INF/web.xml + + + Set the distributable propert= y on + org.jboss.seam.core.init to true to= enable the ManagedEntityInterceptor (i.e., + ]= ]>) + + + Ensure you have two IP addresses available (two = computers, two network cards, or two IP + addressses bound to the same interface). I'll assume t= he two IP address are 192.168.1.2 and + 192.168.1.3 + + + Start the master JBoss AS instance on the first = IP + ./bin/run.sh -c all -b 192.168.1.2 + The log should report that there are 1 cluster m= embers and 0 other members. + + + Verify that the server/all/farm directory is emp= ty in the slave JBoss AS instance + + + Start the slave JBoss AS instance on the second = IP + ./bin/run.sh -c all -b 192.168.1.3 + The log should report that there are 2 cluster m= embers and 1 other members. It should also + show the state being retrieved from the master. + + + Deploy the -ds.xml to server/all/farm of the mas= ter instance + In the log of the master you should see acknowle= dgement of the deployment. In the log of the + slave you should see a corresponding message acknowled= ging the deployment to the slave. + + + Deploy the application to the server/all/farm di= rectory + In the log of the master you should see acknowle= dgement of the deployment. In the log of the + slave you should see a corresponding message acknowled= ging the deployment to the slave. Note that + you may have to wait up to 3 minutes for the deployed = archive to be transfered. + + + + You're application is now running in a cluster with HTTP s= ession replication! But, of course, you are + going to want to validate that the clustering actually wor= ks. + + + + Validating the distributable services of an application= running in a JBoss AS cluster + + It's all well and fine to see the application start succes= sfully on two different JBoss AS servers, but + seeing is believing. You likely want to validate that the = two instances are exchanging HTTP sessions to + allow the slave to take over when the master instance is s= topped. + + + + Start off by visiting the application running on the maste= r instance in your browser. That will produce + the first HTTP session. Now, open up the JBoss AS JMX cons= ole on that instance and navigate to the + following MBean: + + + + + Category: jboss.cache + + + Entry: service=3DTomcatClus= teringCache + + + Method: printDetails() + + + + + Invoke the printDetails() method. You will see a tree of a= ctive HTTP sessions. Verify that the session + your browser is using corresponds to one of the sessions i= n this tree. + + + + Now switch over to the slave instance and invoke the same = method in the JMX console. You should see an + identical list (at least underneath this application's con= text path). + + + + So you can see that at least both servers claim to have id= entical sessions. Now, time to test that the + data is serializing and unserializing properly. + + + + Sign in using using the URL of the master instance. Then, = construct a URL for the second instance by + putting the ;jsessionid=3DXXXX immediately after the servl= et path and changing the IP address. You should + see that the session has carried over to the other instanc= e. Now kill the master instance and see that + you can continue to use the application from the slave ins= tance. Remove the deployments from the + server/all/farm directory and start the instance again. Sw= itch the IP in the URL back to that of the + master instance and visit the URL. You'll see that the ori= ginal session is still being used. + + = + + One way to watch objects passivate and activate is to crea= te a session- or conversation-scoped Seam + component and implement the appropriate life-cycle methods= . You can either use methods from the + HttpSessionActivationListener interface (Seam automaticall= y registers this interface on all non-EJB + components): + + + + + + Or you can simply mark two no-argument public void methods= with @PrePassivate and + @PostActivate, respectively. Note that = the passivation step occurs at the end of + every request, while the activation step occurs when a nod= e is called upon. + + + + + Now that you understand the big picture of running Seam in a c= luster, it's time to address Seam's most + mysterious, yet remarkable agent, the ManagedEntityInterceptor. + + + + + EJB Passivation and the ManagedEntityInterceptor + + + The ManagedEntityInterceptor (MEI) is an optional interceptor = in Seam that gets applied to + conversation-scoped components when enabled. Enabling it is si= mple. You just set the distributable property + on the org.jboss.seam.init.core component to true. More simply= put, you add (or update) the following + component declaration in the component descriptor (i.e., compo= nents.xml). + + + ]]> + = + + Note that this doesn't enable replication of HTTP sessions, bu= t it does prepare Seam to be able to deal with + passivation of either EJB components or components in the HTTP= session. + + + + The MEI serves two distinct scenarios (EJB passivation and HTT= P session passivation), although to accomplish + the same overall goal. It ensures that throughout the life of = a conversation using at least one extended + persistence context, the entity instances loaded by the persis= tence context(s) remain managed (they do not + become detatched prematurally by a passivation event). In shor= t, it ensures the integrity of the extended + persistence context (and therefore its guarantees). + + + + The previous statement implies that there is a challenge that = threatens this contract. In fact, there are + two. One case is when a stateful session bean (SFSB) that host= s an extended persistence context is + passivated (to save memory or to migrate it to another node in= the cluster) and the second is when the HTTP + session is passivated (to prepare it to be migrated to another= node in the cluster). + + + + I first want to discuss the general problem of passivation and= then look at the two challenges cited + individually. + + + + The friction between passivation and persistence + + + The persistence context is where the persistence manager (= i.e., JPA EntityManager or Hibernate Session) + stores entity instances (i.e., objects) it has loaded from= the database (via the object-relational + mappings). Within a persistence context, there is no more = than one object per unique database record. + The persistence context is often referred to as the first-= level cache because if the application asks + for a record by its unique identifier that has already bee= n loaded into the persistence context, a call + to the database is avoided. But it's about more than just = caching. + + = + + Objects held in the persistence context can be modified, w= hich the persistence manager tracks. When an + object is modified, it's considered "dirty". The persisten= ce manager will migrate these changes to the + database using a technique known as write-behind (which ba= sically means only when necessary). Thus, the + persistence context maintains a set of pending changes to = the database. + + + + Database-oriented applications do much more than just read= from and write to the database. They capture + transactional bits of information that need to be tranfere= d into the database atomically (at once). It's + not always possible to capture this information all on one= screen. Additionally, the user might need to + make a judgement call about whether to approve or reject t= he pending changes. + + = + + What we are getting at here is that the idea of a transact= ion from the user's perspective needs to be + extended. And that is why the extended persistence context= fits so perfectly with this requirement. It + can hold such changes for as long as the application can k= eep it open and then use the built-in + capabilities of the persistence manager to push these pend= ing changes to the database without requiring + the application developer to worry about the low-level det= ails (a simple call to + EntityManager#flush() does the trick). + + + + The link between the persistence manager and the entity in= stances is maintained using object references. + The entity instances are serializable, but the persistence= manager (and in turn its persistence context) + is not. Therefore, the process of serialization works agai= nst this design. Serialization can occur + either when a SFSB or the HTTP session is passivated. In o= rder to sustain the activity in the + application, the persistence manager and the entity instan= ces it manages must weather serialization + without losing their relationship. That's the aid that the= MEI provides. + + + + + + Case #1: Surviving EJB passivation + + + Conversations were initially designed with stateful sessio= n beans (SFSBs) in mind, primarily because the + EJB 3 specification designates SFSBs as hosts of the exten= ded persistence context. Seam introduces a + compliment to the extended persistence context, known as a= Seam-managed persistence context, which works + around a number of limitations in the specification (compl= ex propagation rules and lack of manual + flushing). Both can be used with a SFSB. + + + + A SFSB relies on a client to hold a reference to it in ord= er to keep it active. Seam has provided an + ideal place for this reference in the conversation context= . Thus, for as long as the conversation + context is active, the SFSB is active. If an EntityManager= is injected into that SFSB using the + annotation @PersistenceContext(EXTENDED), then that Entity= Manager will be bound to the SFSB and remain + open throughout its lifetime, the lifetime of the conversa= tion. If an EntityManager is injected using + @In, then that EntityManager is maintained by Seam and sto= red directly in the conversation context, thus + living for the lifetime of the conversation independent of= the lifetime of the SFSB. + + + + With all of that said, the Java EE container can passivate= a SFSB, which means it will serialize the + object to an area of storage external to the JVM. When thi= s happens depends on the settings of the + individual SFSB. This process can even be disabled. Howeve= r, the persistence context is not serialized + (is this only true of SMPC?). In fact, what happens depend= s highly on the Java EE container. The spec is + not very clear about this situation. Many vendors just tel= l you not to let it happen if you need the + guarnatees of the extended persistence context. Seam's app= roach is more conservative. Seam basically + doesn't trust the SFSB with the persistence context or the= entity instances. After each invocation of + the SFSB, Seam moves the reference to entity instance held= by the SFSB into the current conversation + (and therefore into the HTTP session), nullifying those fi= elds on the SFSB. It then restores this + references at the beginning of the next invocation. Of cou= rse, Seam is already storing the persistence + manager in the conversation. Thus, when the SFSB passivate= s and later activates, it has absolutely no + averse affect on the application. + + + + + If you are using SFSBs in your application that hold r= eferences to extended persistence contexts, + and those SFSBs can passivate, then you must use the M= EI. This requirement holds even if you are + using a single instance (not a cluster). However, if y= ou are using clustered SFSB, then this + requirement also applies. + + + + + It is possible to disable passivation on a SFSB. See the <= ulink + url=3D"http://www.jboss.org/community/docs/DOC-9656">Ejb3D= isableSfsbPassivation page on the JBoss + Wiki for details. + + + + + Case #2: Surviving HTTP session replication + + + Dealing with passivation of a SFSB works by leveraging the= HTTP session. But what happens when the HTTP + session passivates? This happens in a clustered environmen= t with session replication enabled. This case + is much tricker to deal with and is where a bulk of the ME= I infrastructure comes into play. In thise + case, the persistence manager is going to be destroyed bec= ause it cannot be serialized. Seam handles + this deconstruction (hence ensuring that the HTTP session = serializes properly). But what happens on the + other end. Well, when the MEI sticks an entity instance in= to the conversation, it embeds the instance in + a wrapper that provides information on how to reassociate = the instance with a persistence manager + post-serialization. So when the application jumps to anoth= er node in the cluster (presumably because the + target node went down) the MEI infrastruture essentially r= econstructs the persistence context. The huge + drawback here is that since the persistence context is bei= ng reconstructed (from the database), pending + changes are dropped. However, what Seam does do is ensure = that if the entity instance is versioned, that + the guarantees of optimistic locking are upheld. (why isn'= t the dirty state transfered?) + + + + + If you are deploying your application in a cluster and= using HTTP session replication, you must use the MEI. + + + + + + ManagedEntityInterceptor wrap-up + + + The important point of this section is that the MEI is the= re for a reason. It's there to ensure that the + extended persistence context can retain intact in the face= of passivation (of either a SFSB or the HTTP + session). This matters because the natural design of Seam = applications (and conversational state in + general) revolve around the state of this resource. + + + + + + + + Modified: branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US/master= .xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US/master.xml 2= 009-05-28 19:15:03 UTC (rev 11027) +++ branches/community/Seam_2_1/doc/Seam_Reference_Guide/en-US/master.xml 2= 009-05-29 02:17:32 UTC (rev 11028) @@ -38,6 +38,7 @@ + = = --===============2453669456139245971==--