Sunday, March 27, 2016

Těžkosti a nesmyslnosti kolem rodičovského příspěvku

Zevrubně sepíši, co všechno bylo třeba udělat, aby manželka dostala rodičovský příspěvek.

Výchozí situace:
  • já, zaměstnaný jako Java programátor, příjem vyšší než strop vyměřovacího základu pro mateřskou, půjdu na mateřskou od ukončení 6. týdne dítěte do ukončení 16tého týdne dítěte
  • manželka, samostatná advokátka (www.dobra-advokatka.cz), neplatí si nemocenskou, nemá nárok na mateřskou
  • předpokládané narození potomka koncem dubna 2015
  • bydlíme a pracujeme v Praze, trvalé bydliště máme v Bruntále.

Prosinec 2014

Vědomi si trochu neobvyklé situace, kdy jdu na mateřskou já a manželka nemá nárok na mateřskou (peněžitá pomoc v mateřství, dále PPM), jsme se vydali na správu sociálního zabezpečení zjistit, jaké máme možnosti a co všechno musíme dodat. První překvapení, paní na sociálce nás poslala na pracovní úřad, neb ten má na starosti rodičovský příspěvek. Na pracovním úřadě nám paní dala stoh dokumentů pro manželku a podivila se, jak to máme složité. Konkrétních informací jako šafránu. Úředníci v podstatě nevěděli, co s námi.

Únor 2015

Pracovní úřad trvá na tom, že musí mít rozhodnutí od sociálky, že manželka nemá nárok na mateřskou. To lze získat jen tak, že se o mateřskou oficiálně zažádá. Takže manželce dali na sociálce formulář pro gynekologa, následně jí jej na gynekologii pan doktor podepsal, aby s ním mohla jít zažádat na sociálce o mateřskou, aby dostala rozhodnutí, že na ni nemá nárok (velké překvapení, když si neplatí nemocenskou, což paní na úřadě ví). Takže máme přílohu k žádosti, aby mohl pracák vyplácet rodičovský příspěvek ode dne narození dítěte. Do dubna vyřízeno.

21. duben 2015

Narodil se nám v Neratovicích syn Jáchym :) Po porodu jsme byli čtyři dny v nemocnici, pak ještě několik dní doma.

Květen 2015


Řešil jsem v práci na personálním, co všechno bude třeba vyplnit kvůli mé mateřské, holky mi daly několik formulářů, ty jsem vyplnil. K tomu jsme s manželkou museli podepsat dohodu o svěření dítěte do péče po dobu mé mateřské. Bohužel mužům se v našem státě nevěří, neb na tuto dohodu bylo třeba připojit manželky úředně ověřený podpis – tedy výlet na poštu v šestinedělí. Jinak to bylo od holek na personálním vše. Za mě vyřízeno.
A teď k rodičovskému příspěvku. Vyplnil jsem na internetu na stránkách MPSV pro manželku formulář s žádostí. Práce se šablonou dobrá. Super, že to jde vyplnit na internetu. Nicméně s některými položkami jsem si nevěděl rady (výše příspěvku, přílohy), nápověda nebyla moc nápomocná.
První trochu teorie. Rodičovský příspěvek má maximální celkovou výši 220.000,- Kč. Lze jej pobírat libovolnou dobu mezi druhým a čtvrtým rokem dítěte. Nelze jej pobírat po dobu mateřské, lze jej pobírat nejdříve ode dne narození dítěte. Míra volnosti volby výše příspěvku závisí na výši odvodů. V případě, že člověk nesplní ani stanovenou minimální míru odvodů na nemocenskou, nemůže si vybírat vůbec a musí “volit” čtyřletou variantu, kdy se vyplácí cca 3.500,- měsíčně. Ovšem v případě partnera (nevím, zda musí být nutně manžel), který odvody má, si lze vybírat dle jeho vyměřovacího základu.
A teď zpět k online formuláři. Je tam položka výše rodičáku, což si myslím, že nikdo krom paní na úřadě vůbec nemá šanci spočítat, nejsou k tomu postupy, jak to udělat. Nechal jsem to nevyplněné a museli jsme na úřad stejně osobně. Spočítání výše rodičáku je složité. Například v měsících, kdy je část měsíce na mateřské muž a část žena na rodičáku, ovlivňuje PPM muže výši rodičáku ženy. Tedy v případě vyššího platu (a PPM) manželka v těchto měsících nedostane žádný rodičák, přestože je to jiná osoba, ale zas po tu dobu nebude muset platit zdravotní. Komplikované jak cukrovar.
Dále je tam bod, že pro volbu na základě příjmu partnera je nutné doložit jeho Potvrzení o denním vyměřovacím základu ovlivňujícím výši rodičovského příspěvku nebo Potvrzení o nároku na dávky (náhrady) ovlivňující nárok na výši rodičovského příspěvku. Bohužel jsem si v tu chvíli nepřečetl pozorně jiný bod v sekci v “K žádosti prosím doložte”, psáno malým na konci, a to, že je třeba doložit ten druhý formulář v případě, že jeden z rodičů pobírá PPM – pojmenování formulářů nepomáhá. Takže jsem vytisknul ten první (o denním vyměřovacím základu) a jel s tím na sociálku na Prahu 8. Na formuláři je jen kolonka na denní vyměřovací základ. S přílohou s ročním výpisem příjmů jsem se s důvěrou obrátil na úřednici a čekal, že doplní číslo, razítko, datum, podpis a půjdu. Paní mi řekla, že ať doplním adresu někam na papír (na formuláři na to ani nejsou kolonky!), a že mi to do 30ti dnů pošlou! Při představě rodiny, co nemá rezervy a třeba nižší příjmy velká paráda. Manželka “překvapivě“ moc poslední dva měsíce před porodem nepracovala a na první výplatu rodičáku si ještě počkáme. Jestli vůbec požádáme do konce šestinedělí, bude to zázrak.

4. 6. 2015

Nastoupil jsem na mateřskou.

15. 6. 2015

Byli jsme na sociálce kvůli snížení manželčiných záloh. Bohužel na snížení je třeba mít rozhodnutí o rodičáku. Tak jsme jeli na pracák. Tam manželka čekala spolu s dalšími lidmi před kancelářemi. Já jsem čekal s Jášou v autě. Po nějaké době prostě šla dovnitř, aby našla tři úřednice a žádného klienta. Jedna úřednice brouzdala na internetu, druhá brala třetí míry na kalhoty. Pak úřednice přesvědčovaly manželku, že jdu na rodičák já, než pochopily, že jsem opravdu na mateřské a ona chce rodičák za prvních šest týdnů a na dobu po skončení mé mateřské.
Dále manželka dostala při předchozí návštěvě seznam papírů, co má přinést. Ale chtěly po ní ještě rodný list syna, OK, a oddací list! Oddací list prý potřebují, protože od svatby nebyla žádat o žádné dávky!? K čemu je občanka, ve které má nové příjmení, je mi záhadou. Po mailech jsme naštěstí našli obojí naskenované a vytiskli to, originály byly v Praze. Nato nám paní sdělila, že nám chybí příloha – Potvrzení o nároku na dávky (náhrady) ovlivňující nárok na výši rodičovského příspěvku. To jsme se dozvěděli, že rodičák je ovlivněn mateřskou vyplacenou v tom měsíci. Pořád řešíme výplatu fixních 220 tisíc, ale pravidla jsou dle všeho velmi složitá. V onom chybějícím potvrzení se vyplňuje mé jméno a rodné číslo a jméno a rodné číslo syna. Tedy všechno údaje, které jsou v žádosti o rodičák. Žádný podpis, nic. Přesto musím já tento papír poslat na sociálku, a pak jej odnést na pracák. K tomu ta 30ti denní lhůta. A úřady mají všechny informace, protože jsem už o mateřskou zažádal začátkem května. Plus vše jsme absolvovali se synem, protože kojíme a sám bych ho tři hodiny doma hlídat nemohl.
Taky se nám blíží promlčecí lhůta, neb o dávky lze žádat maximálně tři měsíce zpětně. Díky “rychlosti a ochotě” na sociálce na Praze 8 (v Bruntále tyto věci opravdu dělají na počkání) to možná ani do tří měsíců od narození dítěte nestihneme. Uvidíme.
Plus by se to dalo udělat ještě složitější. Mám jako muž nárok na 16 týdnů mateřské (22 po narození bez šestinedělí). Nevím, jak bychom žádali o rodičák na šestinedělí v případě, že bych nastoupil na mateřskou na 10 týdnů a v půlce se rozmyslel, že chci ještě další měsíc. Řekl bych, že správný postup nakonec je opravdu ten papír s vyměřovacím základem, požádat o rodičák v nějaké výši. Pak nastoupit na mateřskou a dodat další papír? Nevím.

16. 6. 2015

Ježto se formulář s denním vyměřovacím základem dlouho nevracel, poslal jsem 8. 6. email na pražskou sociálku, aby mi obratem vypracovali fikci – použil jsem formulaci a adresu, které mi poradila úřednice při podání toho formuláře 12. 5. Dnes! mi došel email, že můj email dostali a budou se jím zabývat. Takže 30 dní na vyřízení formuláře s jednou kolonkou, 8 dní na přijetí emailu. Je něco shnilého na ČSSZ Praha 8. Formulář mi mezitím přišel do Prahy 12. 6. tedy přesně v oné 30ti denní lhůtě.

Dále

Přesná data v následném vývoji nemám, tak jen shrnu. Na pracáku nám nakonec dali rodičák na šestinedělí na 9.000,- využívajíc papír o vyměřovacím základu. Potvrzení o mateřské mi přišlo dvakrát. Docela to trvalo. Jedno z toho přišlo z ČSSZ Nymburk 16. 9.! Nechápu. Po dodání potvrzení o mateřské jsme na pracáku nastavili maximální výši rodičáku na dobu, dokud bude zbývat něco z těch 220 tisíc a 0,- na zbytek času do dvou let. Pořád nechápu, že jsme kvůli tomu museli tolikrát na dva různé úřady, ke gynekologovi, donést tolik papírů a tolik na všechno čekat. Manželka dostala první rodičák 18. 6., tedy téměř dva měsíce po narození syna. Hlavní prodleva byla způsobena liknavostí ČSSZ na Praze 8.

Shrnutí postupu

  • Žádost o rodičák lze podat až po narození dítěte.
  • Žena bez odvodů musí i tak na sociálku pro papíry pro gynekologa, pak ke gynekologovi, pak na sociálku a počkat na rozhodnutí, že nemá nárok na mateřskou, aby měla papír pro pracák.
  • Při absenci dostatečných odvodů pro určení výše rodičáku lze použít denní vyměřovací základ partnera. Získání takového papíru může trvat i 30 dní. Pro volbu je možné použít i formulář s potvrzením o nároku na PPM, tento je třeba doložit vždy, pokud jde jeden z rodičů na PPM.
  • Po porodu by muž měl upalovat na sociálku, aby získal příslušné potvrzení.
  • V případě že si to můžete dovolit, lze jednoduše počkat, až muži doběhne mateřská, a pak teprve požádat o rodičák. Peníze na rodičák se jen rozdělí do kratšího období, takže o nic nepřijdete a je to administrativně i časově jednodušší, protože systém je nastaven tak, aby tyto podklady byly dostupné až po mateřské.

Návrhy na zlepšení

  • Nenutit ženy, aby chodily ke gynekologům a zas zpátky na sociálku, a pak na pracák, když je zjevné, že na PPM nemají nárok. Sociálka jim může rovnou vydat rozhodnutí, že nemají nárok, aby s tím mohly jít na pracák. Nebo ještě lépe na pracáku podepsat čestné prohlášení, že o mateřskou nežádám a pokračovat rovnou s žádostí o rodičák. Ušetří se práce sociálce, gynekologovi a dvě cesty žadatelce.
  • Nechtít úředně ověřený podpis matky pro svěření dítěte do péče pro účely mateřské otce. To mi přijde genderově nevyvážené. Plus by nebylo nutné nutit matku v šestinedělí do cest na poštu.
  • Pojmenovat lépe formuláře - "Potvrzení o nároku na dávky (náhrady) ovlivňující nárok na výši rodičovského příspěvku" zní pro běžného člověka naprosto neuchopitelně.
  • Vydávat "Potvrzení o vyměřovacím základu" na počkání. V Bruntále to tak prý dělají. V Praze to trvalo celých 30 dní, tedy maximální zákonná lhůta. Plus v mém případě bylo zřejmé, že to bude maximální výše. Stačilo doplnit maximální vyměřovací základ, podepsat, razítko, hotovo. Práce na dvě minuty.
  • Nechtít oddací list na pracáku, když už má člověk novou občanku.
  • Napsat dítě do občanky, nebo rodiče do občanky dítěte. Máme občanku pro malého a stejně s sebou musíme všude nosit jeho rodný list, protože úřednice jinak nevěří, že jsme jeho zákonní zástupci. To je pěkně na hlavu. S rodným listem s sebou můžu vzít jakékoliv dítě a taky mi budou muset věřit, že je moje a je to právě to, co je napsané na rodném listu. Dle úřednice na Praze 8 nemají přístup k údajům lidí mimo Prahu 8. Chápu, ale stačilo by zařídit, aby do systému mohla úřednice zadat čísla občanek, nebo rodná čísla a systém by jí řekl že "Jáchym Burkert je syn Evy Burkertové". Nemusí mít přístup ke všemu, jen k vazbě mezi lidmi. Pak odpadne nutnost nosit s sebou všude ověřenou kopii rodného listu.

Přestěhovali jsme se do Berlína, takže bude následovat pokračování, aneb co v situaci, kdy se přestěhujete do zahraničí. Totiž výplata rodičáku je vázána na pobyt na území ČR. Moc nechápame, že když jsme na území EU, manželka dál pracuje pro klienty v ČR, v ČR odvádí daně, je tam zdravotně i sociálně pojištěna, tak musíme žádat o rodičák v Německu, a pak řešit doplatek do výše v Čechách s českým úřadem práce. Ale o tom až příště.

Thursday, November 13, 2014

Envers: it's slower but at least it doesn't work in some cases

Why not Envers?

Envers is an auditing extension of Hibernate, following the mantra that Java developers should code in Java and not think in terms of the database. Java developers are shielded from the relational features of the database; SQL is evil as it leads to vendor lock-in (when was the last time you switched the database of an existing system?), and the ORM pretends that what you load from the database is objects. The performance often suffers, the framework at times does not support features databases have had from late 80ties and you have to fight its leaky abstraction and bugs. But back to Envers.

Envers comes with limitations that emerge from its very nature. It tracks the Java entities changed within the transaction and then issues inserts into the auditing tables and the revinfo table. For us the main problems of this approach are with its performance:

  • The number of resulting SQL statements is too high. Every insert/update/delete triggers another statement run against the database. These statements need to passed to the database over the wire, increasing the duration of the transaction.
  • Bulk updates, deletes are not supported. Operations such as 'DELETE FROM foo' are not auditable because Envers has no way to know which entities were affected. If you want auditing you have to update every entity separately, leading to potentially many updates and auditing inserts instead of one simple statement.
It should be said that when Envers knows about the entities it works correctly, so for most applications it can be good enough. We used Envers in the prototyping phase of our project but it made it hard for us to handle high loads. Hence, we investigated those relational features we are told to avoid. We put the database to work and replaced Envers with database triggers. There were some turns back and forth and in the end it took us four days to get to a state we are happy with. In this article I want to share our solution for PostgreSQL.

Auditing with database triggers

Auditing

First, let's define what we mean by auditing. We need to audit for regulatory reasons, so we need to know who (which customer, not database user) and when performed what operation. For those tables we need to audit we defined auditing tables which have the same columns as original tables.

Generic Trigger

First, we created a generic database trigger that inserts the row being modified into the auditing table:
There are few things to note here:

  • Auditing table for foo is foo_aud.
  • We used the PostgreSQL trigger variables: TG_TABLE_NAME, OLD, NEW, TG_OP.
  • The query is by design dynamic and must be run with 'EXECUTE ... USING ...'.
  • The construct '$1.column_name' references a column in a record. The record is the first parameter to the dynamic query and is either the NEW or the OLD trigger variable. You don't want to know how long it took me to figure this one out :).
  • The PostgreSQL transaction ID is used to find corresponding row in the revinfo table - see section Who and When bellow.
  • Along with the columns of the original table, the audited table has a varchar 'op' and a integer 'rev' column, containing the operation (insert, update, delete) and the rev from revinfo respectively.

The following script assigns the trigger:

Element collections

Auditing of updates to element collections works out of the box. The respective auditing tables need to have the two columns (op, rev) and the trigger must be assigned.

Who and when

The original goal was to know which user made the change and when. We ripped off Envers and introduced a table like the revinfo table. It contains one row for every transaction that modifies an audited table, together with the who and the when:
The table contains information about the application user, the time and the transaction ID. The transaction ID allows us to link auditing entries to a revinfo row. We cannot use transaction ID directly. It is unique only within one PostgreSQL installation. If we migrate the database to a different server old txid entries might clash with its txid sequence. With our solution, we only need to set txid to null and then migrate the database.

The problem that remains is inserting a row into this table for every write transaction. Ideally, we would insert it only when a transaction modifies an audited entity. So, we added an interface, @AuditedEntity, to mark the audited entities and we registered a listener on the very same events Envers does. The listener then inserts a row into the revinfo table when a transaction performs the first write operation to an audited entity.
A few points to note:

  • The insert must happen before the entity change due to the referential integrity from auditing table to the revinfo table.
  • We need to perform the revinfo insert with session.doWork(). A simple session.createSQLQuery() and then query.executeUpdate() would cause Hibernate to flush the dirty entities.
  • HQL/SQL bulk updates do not trigger Hibernate events, hence we must register the transaction manually using the register(SessionImpl session) method.
  • It is plain evil to use internal Hibernate classes like SessionImpl but we need methods from both SessionImplementor and Session interfaces. Those are combined in the EventSource but that is not available at the point of registering a transaction manually, there we only have the Session. It all boils down to the SessionImpl anyway so we bit the bullet and made the cast. We know we will suffer when we upgrade to Hibernate 5.
We register the events in a ServiceContributingIntegrator:

Conclusion

Our approach performs auditing on the database level. The application only needs to call one insert per write transaction to store user and time information under the transaction ID. The approach supports auditing of SQL/HQL bulk updates.

We haven't done any rigid performance test yet. But we do generate data for the application performance test; it results in inserting approximately 100k rows. The data generation took 50 seconds with Envers auditing, it takes only 35 seconds with database triggers so we look at the improvement of 30%.

Have we overlooked anything? Any suggestions are welcome.

Monday, May 26, 2014

Selenium in Sonar code coverage metrics

Goal

  • Run Selenium GUI tests as part of the build on Jenkins.
  • Collect code usage data to be able to report code coverage on Sonar.

Project Layout

  • Cloudex-parent
    • Core module - services, daos
    • GUI module - for instance Wicket web GUI
    • Test module - Selenium integration tests

Configuration

There are two relevant parts of Maven config - parent POM which defines JaCoCo offline instrumentation and the test POM which covers deployment to embedded Tomcat and running.

parent pom


Test POM

Just few more points:
  • The config module contains build folder with /lib folder with the configuration which needs to be in Tomcat.
  • We need to include jacoco-agent.properties file in the /lib folder from the previous point. It should contain at least a single line: destfile=${sonar.jacoco.itReportPath} (see offline instrumentation).
  • Selenium tests which should run are defined in the testng.xml.
  • We have a dedicated database on external server which is migrated and against which runs the deployed application.
  • The tests run in Firefox on a headless system (Jenkins master) thanks to Xvfb (X virtual frame buffer), so the Jenkins server must have Firefox and Xvfb installed.

Tuesday, July 30, 2013

Non-transactional tests with Spring and H2

The general paradigm for testing Spring based application back-end is to use a sort of unit testing which loads the whole application (the application context) and performs certain tests on it. Spring provides all sort of helper classes among others AbstractTestNGSpringContextTests and AbstractTransactionalTestNGSpringContextTests. I don't know when that decision happened but we always used the transactional one hence every test method run in a separate transaction which was rolled back after each method. It seems to me that such an approach is prevalent in current development yet it is as well flawed.

I bet you encountered cases when the test cannot be transactional, you want to test that your fix for a concurrent race condition works, the locking on the DB does really prevents another user to access something, etc. So you write a non-transactional test class, annotate it with the Spring annotation @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) and you're done. The context is reloaded several times for the start so it's not a big deal. But then you write tens of non-transactional tests and all of a sudden build with tests takes time.

That happened to us and made us thinking, do we need to recreate application context so often? The only reason we do it is that the DB is polluted by the non-transactional tests data. I started the investigation. We use in-memory H2 for our tests. I found that H2 has a wonderful feature which let's you drop its content easily: All you need is the following method in your test parent class:




So no more context recreation. It sped our test build from 1:30 to 55 seconds, boohoo. But than a heretic thought began to creep in our brains. What if we don't need to wrap each test method in a transaction? What if we don't gain much speed there? What if we actually oversee a bug here and there as our tests don't work the same as when client works with the application?

We gave it a try and made all tests non-transactional. The build takes the same time as before as populating and dropping in-memory DB is apparently not an issue, we would do the same in separate transactions anyway. The tests now mimic exactly use cases we want to test as often many transactions happen before the app is in certain state.

We found three bugs straight away. I hope you find some too.

Thursday, January 3, 2013

Non-blocking server push with Atmosphere, Wicket and Spring Security

Previous blog post described how to make Wicket, Spring Security and Atmosphere work together. However, it covered only one part of the story - the blocking transport technique (e.g. long polling). We tried to enable non-blocking protocol and run instantly into several problems emerging mainly from the necessity to use Spring Security filter chain along with Wicket filter and Atmosphere servlet:

The problems were:
  • Spring Security authentication did not work with NIO (non-blocking) connector on Tomcat. My guess is that the filter was not applied.
  • AtmosphereServlet is configurable via atmosphere.xml where you define AtmosphereHandlers. The problem is that you cannot define multiple filters similarly to web.xml.
  • AtmosphereFramework has a regexp which is used to map request path to AtmosphereHandlers mapped to /*. It does not contain underscore which is part of default form-login processing-url of SpringSecurity (j_spring_security_check).
Let's see how we dealt with these problems.

First of all, install the newest version of Tomcat 7 as non-blocking support was developed rather recently and it may not work properly with older versions. We used Tomcat 7.0.34.

Modify the HTTP connector in server.xml

Atmosphere will initiate non-blocking transport only if you include some context.xml in META-INF or exclude atmosphere-compat-tomcat7 from your classpath. We encountered a problem with SpringSecurity SessionFixationProtectionStrategy as request.getSession(true) did not return new session but this was fixed by using newer version of Atmosphere runtime. Our respective pom.xml part looks like this:
Then we need to define the two filters inside AtmosphereHandler defined in atmosphere.xml. We decided to do it programmatically. Here is our atmosphere.xml

And the CustomAtmosphereHandler looks like this:

CustomAtmosphereHandler was inspired by Atmosphere ReflectorServletProcessor. It creates both SpringSecurity and Wicket filters programmatically. In case of Wicket it loads the application in the same manner as the org.apache.wicket.spring.SpringWebApplicationFactory.
Custom FilterConfig gives us control over init parameters. Interestingly, Wicket-Atmosphere integration uses in the mapping filter mapping path from InitParam instead of the filter path set on the WicketFilter. Thus we need to add the init param FILTER_MAPPING_PARAM. We decided to do it this way because otherwise we will have filter configuration scattered over CustomAtmosphereHandler and web.xml.

Our web.xml is then fairly simple:

Now one last finishing touch:) We need to alter default SpringSecurity path so that it is mapped to our CustomAtmosphereHandler so modify the form-login line in your spring-security.xml:

Here is a link to a sample application: http://dl.dropbox.com/u/71731051/push-test.zip

Thursday, December 20, 2012

Apache Wicket + Spring Security + Atmosphere server push

We recently started using Apache Wicket for the front end of one of our new applications. The work on the prototype went fine, well, actually it was a pleasant surprise after two years with JSF.

We have decided to dive into more advanced topics like performance, clustering and server push as we know they'll come on the way and we want to be sure we made right decision by picking Wicket.

I spent last couple of days with my colleague figuring out configuration of Apache Wicket together with Spring Security and Atmosphere framework to allow for server push.

Server push is pretty sleek feature of modern web applications which allows client to subscribe for certain events on the server and then server notifies client (the page in Wicket case) when such an event occurs. Page refreshes without user interaction which comes handy for feeds, messages, etc. There are several transfer technologies at place - starting with long polling and streaming ending with web sockets and SSE. As usual support varies from browser to browser so we can't for instance use only web sockets as they are supported very well by Firefox and Chrome but IE supports them from version 10! (see http://caniuse.com/#search=websocket). Hence we decided to give a try to Atmosphere - framework developed by Jeanfrancois Arcand which claims to mitigate these issues from you. Wicket provides some experimental integration for Atmosphere (wicket-atmosphere - in version 0.5) so let's give it a try.

 (I assume you already have an application using Maven, Spring, Spring Security and Apache Wicket)
pom.xml




Add atmosphere.xml to webapp/META-INF.

The web.xml should look like this:

Few points to the web.xml:

  • We need to provide a custom Broadcaster to the Atmosphere as broadcast happens in different thread, here the SecurityContext is not set to the thread so it results in unauthenticated error hence a redirect to the login page:)
  • Definition of WicketFilter in atmosphere.xml does not allow us to add init-params. Though when AtmosphereFramework sets up filters it provides them servlet context so we can specify applicationFactoryClassName and applicationClassName and it will just work:)

The SpringSecurityAwareBroadcaster looks like this:

Now the application should start and we can use wicket-atmosphere EventBus and @Subscribe to get it working.

In your WicketApplication.java add to the init method:


Now you can subscribe for event in a page by adding method like:


Now let's trigger some event. We have a separate Maven module (let's call it core module) for services and DB access which is not aware of Wicket existence thus we needed to get events to the EventBus from services somehow. Here I would point out Google Guava com.google.common.eventbus.EventBus.

All we you need is to add
to the spring-context.xml of the core module. This can be then autowired to services and in our example in we would have a MessageServiceImpl like:


Then we have to register a handler to Guava EventBus which would then post events to Atmosphere EventBus. Go to the WicketApplication.java and add these few lines:


Now you can schedule for instance a cron job which submits new message every now and then and observe it popping up in the application.

One would thing that that is all. Well, not really. We found out that if you let the session expire it blows up. Well, long story short, Wicket has its WicketSession which has a session ID. Our login page is a Wicket page so this session ID is set from the first http session which is created when user enters the page. Spring Security has a SessionFixationProtectionStrategy which invalidates this HttpSession and creates new one with authentication in onAuthentication method. Hence WicketSession ID no longer matches HttpSession ID. That was not a problem until we started with Atmosphere.

Wicket-Atmosphere EventBus manages subscriptions to events. It also unsubscribes client when session expires (in unboundSession method). The subscription is identified by a page and by a session ID. I guess you sense the disruption in the Source here;). The problem is that client subscribes under the WicketSession ID which is the ID of the first HttpSession. When it unsubscribes in sessionUnbound() it uses the second HttpSession ID hence it does not unsubscribe client and EventBus keeps sending events to that subscription.

We handled this problem by adding a RequestCycleListner in the WicketApplication. This listener removes old HttpSession from WicketSession and binds the new HttpSession to it.


The Listener looks like this:



Well, we will be happy to hear your comments.