Blog do projektu Open Source JavaHotel

sobota, 29 listopada 2014

Byliśmy na operze

28 października byliśmy w Teatrze Wielkim na operze Andrzeja Czajkowskiego  "Kupiec wenecki", bardzo nam się podobało.

"Kupiec wenecki" to budząca kontrowersje sztuka Szekspira ze względu na złowrogą postać mściwego Żyda i lichwiarza Shylocka. Budzi kontrowersje oczywiście według współczesnych standardów politycznej poprawności, w czasach Szekspira i późniejszych doskonale wpasowywała się w obowiązujące wówczas antyżydowskie stereotypy.

Ale początkową przyczyną zainteresowania tą sztuką Czajkowskiego, żydowskiego ocaleńca z Zagłady nie była chęć zmierzenia się z tym antysemickim bagażem, ale piękny fragment z V aktu odnoszący się do  muzyki:
How sweet the moonlight sleeps upon the bank.
Here we will sit and let the sounds of music / strains
Creep in our ears. Soft stillness and the night / Let
Become the touches of sweet harmony.
Opera Czajkowskiego jest jednak przede wszystkim współczesnym odczytaniem sztuki na scenie operowej, a nie spojrzeniem na problem antysemityzmu. Oczywiście, dla potrzeb sceny zostały dokonane pewne skróty i przesunięcia, np. zniknęła postać błazna Lancelota, zamiast monologów Księcia Maroka i Księcia Aragonii jest pantomima, zaś mowa Shylocka pojawia się w scenie sądu. Jednak ciągłość i integralność samej sztuki jest zachowana i wiernie oddana. Mocnym akcentem, wykrzyknikiem Czajkowskiego, jest tylko potężny krzyk tłumu "Żyd" jako ostateczne pohańbienie Shylocka po przegranym sądzie. W epilogu realizatorzy wprowadzili niemą postać Shylocka, który skrapia głowę wodą na znak chrztu i zapada się w grobie. Podkreśla to jedność losów Antonia i Shylocka, jeden traci córkę i religię, a drugi ukochanego Bassania, jeden jest wykluczony jako Żyd, a drugi jako homoseksualista.

Inscenizacja przenosi akcję w czasy bardziej współczesne. Nie ma tutaj weneckiego karnawału, kanałów czy pałaców. Scena, gdy Antionio pożycza pieniądze od Shylocka to świat biznesu, królem jest pieniądz. Ucieczka Jessiki i grabież domu Shylocka nasuwa skojarzenia z ponurymi wydarzeniami z czasów III Rzeszy, ale to raczej inwencja realizatorów, a nie zamysł kompozytora.

Głównym elementem scenografii są dwa prostokątne bloki zmieniające swoje położenie, raz przedstawiają salę giełdy i bankierów, a innym razem uliczkę w mieście, zaś innym razem wnętrze domu bogatej dziedziczki Portii. Wiele scen jest wizualnie bardzo pięknych, np. scena z Księżycem w pełni czy scena wyboru pudełka przez Bassania i następującej radosnej zabawy. Czasami ma się jednak wrażenie, że na scenie dzieje się za dużo, sama inscenizacja skupia nadmierną uwagę.

Kulminacyjną sceną jest oczywiście scena sądu, konflikt między wezwaniem do okazania miłosierdzia i zapiekłym dążeniem do wywarcia zemsty przez Shylocka. Bardzo dobrze się tutaj wpasowuje przemowa Shylocka.
Hath not a Jew eyes? Hath not a Jew hands, organs,
dimensions, senses, affections, passions; fed with
the same food, hurt with the same weapons, subject
Nasuwa się tutaj analogia z innym słynnym monologiem.
Tylko dlatego, że się dobrze urodziłeś (hrabio Almaviva),
to już uważasz że jesteś geniuszem ? ..
Co to takiego uczyniłeś, że doszedłeś do takiej fortuny ?
Tylko tyle, że się dobrze urodziłeś i nic więcej !
Shylock w swojej zaciekłości brnie do samego końca, ale zaplątuje się we własne sidła i pada ofiarą perfidnej, prawniczej sztuczki. Cieszymy się, że dobry i szlachetny Antonio ucieka sprzed noża, ale trochę dreszcze nas ogarniają.

Wykonawcami jest międzynarodowy zespół, ale trudno powiedzieć, żeby jedna rola dominowała nad całością i zapadała w pamięć, nawet słynny kontratenor Christopher Robson w roli Antonia. Robson, bardzo wyrazisty wykonawca i posiadający głos o specyficznej barwie zdawał się być idealnym wykonawcą roli Antonia, postaci kruchej, wrażliwej, płaczliwej, zmiennej w nastrojach. Wykonawcami ról Shylocka i jego córki Jessici są ciemnoskórzy wykonawcy (Lester Lynch i Marisol Montalvo), ale nie należy się w tym doszukiwać próby zbudowania pomostu pomiędzy wykluczeniem Żydów i rasizmem. W tej inscenizacji raczej podkreśla obcość, odmienność. Jessica nawet w epilogu, po wyrzeczeniu się ojca, religii i poślubieniu chrześcijanina jest dalej obca (tak samo jest przecież w sztuce Szekspira) i kolor skóry to podkreśla, jest znamieniem nie do zdarcia.

Główną wartością przedstawienia jest wspaniała i niezwykła muzyka. Można szukać podobieństw do "Króla Rogera" Szymanowskiego czy "Zamku Sinobrodego" Bartoka, oczywiście, w samej strukturze, a nie poprzez bezpośrednie zapożyczenia. Muzyka nie jest tłem dla sceny, podkreśleniem czy zaakcentowaniem akcji która się dzieje, ale podąża za słowem czy nawet gestem. Nie ma przerw, nawet chwili wytchnienia, muzyka cały czas jest obecna, jej gęstość niemal fizycznie się wyczuwa. Stawia duże wymagania wykonawcom, ale także słuchaczom, wymaga skupienia i ciągłego nadążania za frazą.

Słuchając tego pięknego przedstawienia trudno zrozumieć, dlaczego tak wspaniałe dzieło pokrywało się kurzem przez ponad 30 lat. Trzeba mieć nadzieję, że teraz, gdy kurz został starty i blask przywrócony wejdzie na stałe do repertuaru operowego.

Więcej informacji o Kupcu Weneckim Czajkowskiego - tutaj.

poniedziałek, 17 listopada 2014

Google App Engine and Jython 2.7beta3

Problem
I spent several sleepless nights trying to figure out why Jython 2.7beta3 suddenly refused to work in Google App Engine while Jython 2.7 beta2 worked nicely.
It crashes while initializing site.py standard package because Google App Engine blocks any attempt to use ProcessBuilder.

com.jythonui.client.service.JythonService.runAction(com.jythonui.shared.RequestContext,com.jythonui.shared.DialogVariables,java.lang.String,java.lang.String)' threw an unexpected exception: Traceback (most recent call last):
  File "/base/data/home/apps/s~testjavahotel/5.380117830403911812/WEB-INF/lib/jython-standalone-2.7-b3.jar/Lib/site.py", line 571, in 
  File "/base/data/home/apps/s~testjavahotel/5.380117830403911812/WEB-INF/lib/jython-standalone-2.7-b3.jar/Lib/site.py", line 552, in main
  File "/base/data/home/apps/s~testjavahotel/5.380117830403911812/WEB-INF/lib/jython-standalone-2.7-b3.jar/Lib/site.py", line 231, in check_enableusersite
 at jnr.posix.JavaPOSIX.geteuid(JavaPOSIX.java:102)
 at jnr.posix.LazyPOSIX.geteuid(LazyPOSIX.java:115)
 at org.python.modules.posix.PosixModule.geteuid(PosixModule.java:343)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:45)

java.lang.NoClassDefFoundError: java.lang.NoClassDefFoundError: Could not initialize class jnr.posix.JavaPOSIX$LoginInfo

 at com.google.gwt.user.server.rpc.RPC.encodeResponseForFailure(RPC.java:389)
 at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:579)
 at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:265)
 at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:305)
 at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
This exception (raised in Development and Production mode) can be resolved easy by setting Options.no_user_site = true; before starting the Jython interpreter.

But then came up the second one which unveils only in Production mode (works in Development mode).
javax.servlet.ServletContext log: Exception while dispatching incoming RPC call
com.google.gwt.user.server.rpc.UnexpectedException: Service method 'public abstract com.jythonui.shared.DialogVariables com.jythonui.client.service.JythonService.runAction(com.jythonui.shared.RequestContext,com.jythonui.shared.DialogVariables,java.lang.String,java.lang.String)' threw an unexpected exception: Traceback (most recent call last):
  File "__pyclasspath__/site$py.class", line 571, in 
  File "__pyclasspath__/site$py.class", line 553, in main
  File "__pyclasspath__/site$py.class", line 286, in addusersitepackages
  File "__pyclasspath__/site$py.class", line 261, in getusersitepackages
  File "__pyclasspath__/site$py.class", line 250, in getuserbase
  File "__pyclasspath__/sysconfig$py.class", line 112, in 
  File "__pyclasspath__/posixpath$py.class", line 391, in normpath
AttributeError: 'NoneType' object has no attribute 'startswith'

 at com.google.gwt.user.server.rpc.RPC.encodeResponseForFailure(RPC.java:389)
 at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:579)
 at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteService
Attribute sys.prefix is None for some mysterious reason. Because debugging in Production mode is impossible the only way was to compile Jython from sources (which is not trivial for the first time), add logging messages and trying to encircle the bug. Finally I realized that in Google App Engine Production mode system property "java.class.path" is null.  So the code
        if (root == null) {
            String classpath = preProperties.getProperty("java.class.path");
            ll.warning("classpath=" + classpath + "!");
            if (classpath != null) {
                String lowerCaseClasspath = classpath.toLowerCase();
                int jarIndex = lowerCaseClasspath.indexOf(JYTHON_JAR);
                if (jarIndex < 0) {
                    jarIndex = lowerCaseClasspath.indexOf(JYTHON_DEV_JAR);
                }
                if (jarIndex >= 0) {
                    int start = classpath.lastIndexOf(File.pathSeparator, jarIndex) + 1;
                    root = classpath.substring(start, jarIndex);
                } else if (jarFileName != null) {
                    // in case JYTHON_JAR is referenced from a MANIFEST inside another jar on the
                    // classpath
                    root = new File(jarFileName).getParent();
                }
            }
        }
        if (root == null) {
            return null;
        }
does not find the root path for Jython libraries. There is a bug in this code because clause:
 
   } else if (jarFileName != null) {
                    // in case JYTHON_JAR is referenced from a MANIFEST inside another jar on the
                    // classpath
                    root = new File(jarFileName).getParent();
                }
            }
should be placed outside if classpath != null clause (not inside) and root directory cannot be extracted from Jython jar file path as well.
Solution
But finally I found the solution and it was simple as usual.
 
    protected PythonInterpreter(PyObject dict, PySystemState systemState, boolean useThreadLocalState) {
        if (dict == null) {
            dict = Py.newStringMap();
        }
        globals = dict;

        if (systemState == null)
            systemState = Py.getSystemState();
        this.systemState = systemState;
        setSystemState();

        this.useThreadLocalState = useThreadLocalState;
        if (!useThreadLocalState) {
            PyModule module = new PyModule("__main__", dict);
            systemState.modules.__setitem__("__main__", module);
        }
        
        if (Options.importSite) {
            // Ensure site-packages are available
            imp.load("site");
        }

So it was enough to set Options.importSite = false; before launching PythonInterpreter and the whole stuff related to site.py (useless in Google App Engine restricted environment) is disabled.

niedziela, 16 listopada 2014

New version of JavaHotel application

Introduction
New version of JavaHotel application is deployed to Google App Engine (User/Password user/user). Source files are available here.
Changes implemented:
  • Visualization of the reservation state in the reservation panel
  • Advance deposit for guaranteed booking
  • More convenient to work with reservation
  • Confirmed/Not confirmedbooking
  • Access to the reservation data from the list of reservations (not only from reservation panel).
  • Warning before making the reservation persistent without refreshing it.
Visualization of the reservation state

The following states are recognized:
  • Reservation scheduled (not confirmed)
  • Reservation confirmed
  • Reservation, advance deposit paid by the customer
  • Reservation, advance deposit payment date expired
  • Customer not arrived. Current date is greater then the beginning of the reservation  and no check-in yet
  • Vacant, not paid. Last day of the stay expired and the bill is not balanced
  • Vacant. Last day of the stay expired and fully paid
  • Vacant excess payment. Last day of the stay expired and the payment exceeds the bill
  • Occupied, not paid.
  • Occupied, advance paid. Advance deposit payment exceeds the bill still
  • Occupied paid
  • Occupied excess payment (including advance deposit)
Advance deposit for guaranteed booking
During making the reservation an advance deposit can be specified.

 The advance deposit amount can be entered directly or calculated automatically as a percentage of the total payment. The advance deposit payment date can be specified also.
Important: Current version supports advance payment only as an additional information for the operator. No automatic action is performed.
The advance deposit data can be specified also later by changing the existing reservation.

The dialog allows also to enter payment done by the customer.

More convenient way of working with the existing reservation
After clicking the reservation in the panel a smaller windows pops-up.
This window allows simpler access to some functionality related to the reservation. After clicking on "Change reservation" the full reservation dialog is displayed.
Confirmed/not confirmed
Reservation can be marked as confirmed/not confirmed. This indication can be specified at the beginning and can be modified later. Important: confirm/not confirmed status is only for an information, no automatic action is implemented.
Access to the reservation data also from reservation list
"Administration" -> "Reservations"
List of reservations displays also reservation status. After clicking the column the reservation (or stay) details are displayed. It is the same dialog window as in the reservation panel. Also reservation (or stay) modifications can be done here.
Warning before making the reservation persistent
Reservation (also modification) should be done in three steps:
  1. Fill reservation data (number of days, number of persons, price list etc)
  2. Refresh the reservation. It applies reservation data entered in step 1 and recalculates it. Also checks if reservation does not overlaps with other reservation. 
  3. Make reservation. It makes the reservation persistent. Uses the result of the last refreshing. So if user omits step 2 the final result can be different then expected.
In order to  minimize the risk of confusion a warning window is displayed signalizing that some changes were made without refreshing the reservation.



The user can finalize reservation (ignoring changes) or return to the booking dialog.

Next steps
  • Taxation
  • Reports