Blog do projektu Open Source JavaHotel

Pokazywanie postów oznaczonych etykietą GoogleAppEngine. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą GoogleAppEngine. Pokaż wszystkie posty

poniedziałek, 31 października 2016

New features in Jython MVP framework, more Polymer

Introduction
I implemented next bunch of Polymer web components from GWT Polymer show case. New components implemented: Header Panel, Icon Button, Item, Input, Material, Menu, Progress, Radio Button, Radio Group, Ripple, Spinner, Tabs.
The demo is launched from here, the source code is here.
Example screenshots


ui:style
I also implemented ui:style element with CSS class name obfuscation. This way we can have a "private" CSS class name without the risk, that "local" class name will collide with other CSS class definitions. Also, the framework does not allow to use misspelled class names.
An example for UIBinder with ui:style element.
Pending problems
  • Popup dialogs do not work in Firefox browser
  • Not all web components render well, for instance: Tabs
  • Implementation of Progress component is still waiting for action for "Start" button
Next steps
Continue with Paper components. Having ui:style element implemented, makes copying and pasting UIBinder files from GWT Polymer show case easier.



sobota, 30 lipca 2016

New features in Jython MVP framework

Introduction
I started playing around with Vaadin Gwt Polymer and decided to implement this feature in my Jython MVP framework. The source code is available here, show demo version can be launched through this address (it could take several minutes until Google App Engine instance is activated). Important : does not work properly in Firefox, tested with Chrome only.
New features are consumed in two ways:
Polymer implementation


XML definition
In order to activate Polymer rendering "polymer" attribute should be added. Widgets implemented so far: menu, combo (PaperDropdownMenu), main panel, editing. A list is not implemented yet. A date picker is implemented by standard GWT DatePicker widget, I was unable to find Polymer equivalent.
Dynamic UI Binder
Polymer rendering described above comes with one obstacle. In order to give access to all Polymer properties, it would be necessary to extend the xml definition by a huge number of additional attributes mapping to appropriate Polymer properties. It is resolved by GWT UiBinder which is not applicable for Jython MVP framework because UI Binder is resolved statically, during compilation. So I decided to develop my own UI Binder implementation, resolved dynamically. In a sample application, I implemented several Paper Elements from Vaadim GWT Polymer show case.
GWT UI Binder format is not mutually intelligible with MVP Jython UI Binder format. But both share the logic, I found quite easy to adapt UI Binder from Vaadim show case for a  sample application. An example of UIBinder for above dialog is available here, fieldid attribute binds UIBnder element with corresponding field or button element, like GWT UIBinder ui:field attribute.
Java code for dynamic UI Binder is here. Of course, it is not possible to use reflection in GWT context, so the only solution is a painstaking manual setting of all corresponding attributes.
Next steps
Implementing all samples from GWT Vaadin Polymer show case.


czwartek, 31 grudnia 2015

New version of JavaHotel application

Introduction
The new version of JavaHotel application has been deployed. Demo version (U/P user/user), full source code is available here. A new option is a journal, a register of daily activities of the user. The journal gives the manager an insight into daily business and workload of all users.
Journal
Journal is available from upper menu: Administrator->Journal

A subset of user action is recorded, the actions related to changes in the status of database and reservation or some customer actions like sending a confirmation note or registering a payment.
Filtering
Also, a convenient journal filtering is implemented. Activities can be filtered on users and activity type.


Future

  • Graphic presentation of journal
  • More granular reporting related to the time of the day, answering the question: "at what time of the day some type of action is more frequent ?"

czwartek, 8 października 2015

New features in Jython MVP framework

Introduction
I added several improvements to Jython MVP framework. The source code is available here. Demo version running in  Google App Engine is here.
Change focus
This feature allows an automatic jump to the particular field in the form. Is useful at the beginning allowing user start entering data in the proper field or, in case of error detected, move to the wrong field. This option is demonstrated in the demo application, Alerts -> Dialog with focus.

More detailed description.
Field with dynamic list of images
This option was created firstly for the editable list. But now it is extended to form as well. Declaration and handling are very similar. More details. The option is showed in the demo application, Alerts -> Dialog with image field.

sobota, 11 lipca 2015

New version of MVP Jython framework

Introduction
New version has been deployed. Introduces new functionality and enhancements.
Source code and and Google App Engine demo version.
Hide and show columns in list programmatically
Columns can be hidden and revealed again from Jython code. More detailed description is available here.
Demo version: Different lists->Change header name. After clicking "Column 2 visible" check box "Number 2 column" disappears or reappears.

Remember feature
Entering data is very dull task but "remember feature" provides some relief. Just restores value used last time. So far it could be achieved programmatically but from now on it is done automatically by adding "remember" attribute to a field description. Value can be remembered for each field individually or several fields can share the same value. More detailed description is available here.
Demo version : Alerts -> Dialog with remember.

Fields "Remember us" shares the same remembered value.
Suggest feature
"Remember" recalls only one last value but "Suggest" brings back a list of values to choose from. To implement "Suggest feature" GWT SuggestBox widget is used. Suggest list can be static or dynamic. Static gives the same list of predefined values all the time. Dynamic is enhanced automatically, every time user enters new value it is added to the list. In case of overflow the oldest value is removed. List can be stored individually for each field or the same list can be shared between different fields. More detailed description is available here.
Demo version :  Alerts->Dialog with suggest.

"Suggest custom" is using a static suggest list and "Suggest" dynamic
Get data
Data from any list can be downloaded or send to the recipient. Just click: "Tool" -> "Get data".


Several formats are supported: cvs, xml, html, JSon and PDF.

niedziela, 17 maja 2015

New version of MVP Jython framework

Introduction
New version of MVP Jython framework was deployed. New features had been added and several bugs fixed.
Sample application (Google App Engine)
Source code
Change title(tooltip)
More detailed description 
Change column header
More detailed description
Sample application Different lists -> Change column header
After clicking "Change column header" button column header will be modified accordingly.
Changes saving
User can modify some parameters related to list. For instance: number of rows.

So far the changes were active only for a current window. After refreshing standard values were restored. From now on the changes will be persisted in browser cookies and reused.
Modify the list layout
Additional option is implemented : "Change column settings"


After selecting the option it is possible to modify column headers and visibility.

Changes are persistent, new layout is stored in browser cookies. It is possible also to restore standard layout by clicking "Restore default" button.
Important: changing column order is planned in the future.
Setting/unsetting all column
Sample application Different lists -> List check
In "list edit" mode (more details) one can make "bool" column editable for check/uncheck. Option has been added to check/uncheck all list after clicking the column header. Whole list is modified, not only a single row.
Important: Side effect is involved because clicking the header causes also list sorting by boolean values. Will be improved in the future.
Small fixes
  • Footer numerical value is formatted like number in the column (decimal point, spaces between thousands). 
  • Jython 2.7 (final release) is used. Unfortunately, nasty problem was detected while converting date time value to Java Timestamp (source code modifier). Also this version does not work in Google App Engine (java.io package) so the old Jython 2.7-b3 is deployed for this version.
Future
  • List: download as csv, PDF (for printing) and send as an attachment in mail.

niedziela, 1 lutego 2015

New version of JavaHotel, taxation

Introduction
I uploaded new version of JavaHotel application. Demo version (U/P user/user) is available here, source code here.
Taxation
While issuing a document (receipt, bill) a taxation is calculated using tax level assigned to the service.

Detailed information related to the document is also available. This information if stored in the database (as XML file) for every document issued.
Taxation information is also exposed in "Stay summary" window providing information about the current status of the stay.
Next step 
Receptionist journal registering the information about user activity.

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

wtorek, 23 września 2014

New version of JavaHotel, mailing

Introduction
I deployed new version of JavaHotel application. Google App Engine demo is available here (U/P user/user), source code can be downloaded here. New feature is mailing.
Booking
Sending a confirmation mail is a part of the booking process. After successful booking confirmation note can be sent immediately.

If answer is yes then a window with note content pops up.

The note content is generated automatically through XSLT transformation. XSL source file is available here. By extending XSL source file it is possible to modify the confirmation note content: add some graphics, information about cancelation policy, payment method etc. Note content can be also modified manually before sending.
Confirmation email can be sent also later or resent again in case of reservation changing.


Mailing PDF receipt
Automatic mailing is enabled for PDF receipt. Hotel guest can ask for a second copy of the receipt after leaving the hotel or wants to make some changes in the receipt content (for instance address data).
The receipt PDF is attached to the note. The content of receipt note is also generated using XSLT and can be modified as desired.

Email collecting
All notes sent from the application are stored internally in the database (independently from 'Send' folder in the mail box).
The user can review all notes related to the particular reservation.


Also all notes sent to the customer/guest can be reviewed.


Next step

Advance payment.

wtorek, 26 sierpnia 2014

MVP Jython framework and mail handling

Introduction
I deployed a new version of MVP framework containing mail handling. Google App Engine demo version is available here (Mail ->Send mail (save)). The purpose is not to create another mail client but to provide simple Jython interface for mail sending (cmail.py). The solution also stores mail sent in the database for future reference.
This interface will be used later in JavaHotel application for tasks like: reservation confirmation, invoice sending etc.
In JEE version JavaMail is used, in Google App Engine Mail Java Api is used.
Test GUI
Sample application contains GUI for testing purpose, a sample usage of cmail.py interface. The test code is available here.
List of mails sent (taken from database, not from 'Sent' folder).


Mail sending (with attachment)
List of attachments from note already sent
Future
Apply the solution is JavaHotel application.

niedziela, 29 czerwca 2014

JavaHotel, new version

Introduction
I deployed next version of JavaHotel application. Demo version (Google App Engine) is available here (U/P user/user) and source code here.
Searching
I added a searching (so far new reservation was activated after clicking in the hotel room/day cell).
After clicking "Search" button a list of hotel rooms available is displayed :
and the user can select a room and a reservation can be started.
Reservation extension
After reservation is booked it is possible to extend it by adding another room to the reservation or extend the reservation period for the room already booked.  This option is available after clicking "Extend reservation" button.
 It is the same searching mechanism as above but after clicking "Add to reservation" button the room selected is added to the existing reservation.
Reservation modification
Also more detailed modification of existing reservation is possible after clicking "Modify reservation" button.

The user can modify reservation for the single day/room line, remove one line from the reservation and add a new line.
Customer/guest info
This option is available through "Upper menu" -> "Administrator" -> "List of customers" -> "Info".
This window shows the activity of the particular customer.
Room/service info
"Upper menu" -> "Administrator" -> "Services" -> "Modify" -> "Show rooms"
List of hotel rooms sharing this service.
Additional changes
  • Modifying list of guests (checked in) also during a stay.
  • "Administrator" - blockage for removal objects (rooms, customers, services, price list) if there exists any dependent object (for instance: cannot remove a hotel room if there is exist a reservation for this room). Future: add option "out of use" or "deactivate" the object.
  • "Spinner" widget (look above) to make user interface more user friendly.
Next step
Implements charts (I'm going to use Google Charts ) to visualize room, service or customer activity.

piątek, 20 czerwca 2014

MVP Jython framework, new enhancements

Introduction
I added several enhancement to MVP Jython framework. Sample application is available here, source code here.
URL parameters
Access to URL parameters in the Jython backing code. It allows passing some additional parameters to the application.  Description is available here. In the sample application : Different lists -> URL params.
Additional standard toolbars for list
It is the small enhancement but allows to avoid repeating the same sequence of buttons. Description is available here.
Application parameters
This enhancement allows injecting some application parameters into the dialog definition. Description is available here.
Spinner widget
Spinner widget allows entering integer values without typing keyboard. It is convenient method if the range limit is not very big. Sample application : Status -> Spinner and Status -> List with spinner. For dialog form spinner range values can be modified dynamically. Description is available here.
JavaScript backing method
JavaScript function can be defined as a response action. Because JavaScript is executed at the client side and it makes user interface more agile. Defining JavaScript response action is possible only if server side action (for instance database querying) is not required. Sample application : Alert -> Dialog with JS. Description is available here.

środa, 21 maja 2014

JavaHotel, Jython 2.7 and Google App Engine

Introduction

I decided to go ahead and upgrade Jython I'm using from Jython 2.5 (Jython 2.5.4rc1) to Jython 2.7 (Jython 2.7beta2). It works without any problem but I was stuck after deploying to Google App Engine.  The exception error was as follows:

Caused by: java.lang.ExceptionInInitializerError
 at jnr.posix.POSIXFactory.(POSIXFactory.java:15)
 at org.python.modules.posix.PosixModule.(PosixModule.java:63)
 at org.python.modules.Setup.(Setup.java:29)
 at org.python.core.PySystemState.initBuiltins(PySystemState.java:1317)
 at org.python.core.PySystemState.doInitialize(PySystemState.java:1056)
 at org.python.core.PySystemState.initialize(PySystemState.java:982)
 at org.python.core.PySystemState.initialize(PySystemState.java:938)
It was very nasty because it worked in Development Mode (local environment) and it is not easy to debug the application after deploying to the production environment.

Solution 

After spending some time, analyzing exception stack and digging through different versions jnr-posix module (used by Jython for system related stuff) especially Platform class I found the solution.  It was because Google App Engine does not set os.name property (it is null). So the solution was to enhance appengine-web.xml file.
  <system-properties>
    ......
    <property name="os.name" value="linux"/>
    <property name="os.arch" value="amd64"/>    
  </system-properties>
It works now but two questions are pending around me:
  • How it worked with Jython 2.5
  • While Google App Engine set this variables in Development Mode and does not set in Production Mode.

niedziela, 4 maja 2014

Enhancement to MVP GWT/Jython framework

Introduction
I added several enhancement to my MVP framework. Source code is available here, the demo version (deployed to Google App Engine) is available here. I'm planning to use this enhancements in the JavaHotel application. The description is available here.
Disclosure panel
It is an utilization of GWT DisclosurePanel. Demo version: link -> Different lists -> Dialog with disclosure. I'm planning to use it for more advanced room booking options (group booking). Because in most cases a single room is booked it is not necessary to expose group booking options all the time. The implementation also raises Jython action events before opening and closing the disclosure panel.
Autohide dialog
It is a GWT DialogBox widget with 'autoHide' constructor parameter set to true. Demo version: link -> Autohide dialog. I'm using this feature while exposing the link for PDF downloading. This link is enclosed in autohide dialog just making removing this small dialog more convenient.
Modeless dialog
It is a GWT DialogBox with 'modal' constructor parameter set to false. link -> Modeless dialog ->Modeless. After displaying the last dialog it is still possible to enter values into underlying dialog.I'm planning to use it in the JavaHotel application for more sophisticated searching.
Unfortunately, working with modeless dialog causes some complications and questions. For instance : whether modeless dialog should be removed while underlying dialog is closed ? It requires more elaboration.
Programmatic switching active line in lists
As a default the active line in the list immediately after creation is not specfied. The user should manually navigate to the other lines if necessary. I added the programmatic way of changing the active line - for instance - to implement more advanced searching. link -> Different lists -> List with custom search. I'm planning to use this option for more advanced booking.
Programmatic change active line in dateline panel
This problem is similar to above but is related to dateline widget. link -> Panel date -> To date.
URL query string
Allows passing parameters from query string to Jython backing code. More details.
Strange thing while deploying JSPWiki for Clouds application
I spent some time trying to resolve log message:
Unsupported major.minor version 51.0
The meaning of this  message is obvious: one is trying to execute java code in JVM not supporting this Java version. For instance: byte code created with JDK 1.8 in JVM 1.7. I indeed launched Eclipse with JDK 1.8 but JSPWiki code was compiled having 1.7 compatibility level. This message was throws from JSP (not pure Java) code.
I discovered that this message is thrown after executing the application on local machine in Development mode before deployment to Google App Engine. Probably the JSP pages are compiled at that moment and later I was unable to find any way to force recompiling it in 1.7 compatibility mode. After relaunching the Eclipse with JDK 1.7, running the application locally and redeploying it to Google App Engine again the problem disappeared.

czwartek, 24 kwietnia 2014

Java Hotel, new version, printing and pdf generating

Introduction
I deployed new version of JavaHotel application to Google App Engine infrastructure. The version is available here and source code for all application is available here (U/P user/user). This version contains PDF generating for bill issued and receipt printing (from PDF). It is also possible to save PDF created and reprint it later.
PDF generating
After issuing a bill there is a "print" button in the bill list. After clicking the button a html preview of the receipt is presented (it is very rough now, requires more elaboration for real use).
The user can download the PDF (after clicking the receipt.pdf link) and print and save PDF with description for later reuse
The PDF is generated from the HTML view.

If PDF is saved then it is available for later reuse. More the one PDF can be saved for a single bill (for instance in case of correcting) to keep all documents given to the customer.

The user can download and print again the PDF and edit the description.
How it is done
The receipt (as HTML) is generated through XSLT transformation. An example used here is available here. It is very convenient and allows to align receipt form without modifying the application. It is also possible (will be implemented later) to use more then one receipt format for different customers and services.
PDF is generated from HTML by means of iText software.
XSLT and Google App Engine
After deploying the application to Google App Engine I spent some time fighting with (in Development Mode worked correctly):
transformer = tFactory.newTransformer(StreamSource(iS.openStream())) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.defineTransletClasses(TemplatesImpl.java:352) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:366) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:399) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:634) 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) javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerConfigurationException: Translet class loaded, but unable to create translet instance.
After applying the solution described here (deploy all jars related to xalan) the problem was resolved.
Glassfish 4.0 and GWT 2.6
I spent also some time working with problem related to Glassfish 4.0 (the same for WildFly-JBoss) and GWT 2.6
Severe: Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Set] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject com.google.gwt.thirdparty.guava.common.util.concurrent.ServiceManager(Set)] org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Set] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject com.google.gwt.thirdparty.guava.common.util.concurrent.ServiceManager(Set)] at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403) at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:325) at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:177)
The problem is related to Guava rather but because the Guava seems to be included in gwt-servlet.jar so the problem was inherited accordingly. I'm using also Guava but before 2.6 I utilized Guava embedded in Glassfish.
The hot discussion around this issue is available here.
The problem disappeared after applying the solution described there.

  1. Prepare beans.xml file:
  2. <beans bean-discovery-mode="none" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"></beans>
  3. Unpack standard gwt-servlet.jar 
  4. Put this file into META-INF directory 
  5. Pack gwt-servler.jar and use it instead of original one.

poniedziałek, 3 marca 2014

Jython MVP, enhancement

Introduction
I added several enhancement to MVP Jython framework. The source code is available here. The sample application (Google App Engine) is available here.
Show, hide, enable and disable buttons
The description is available here.
Custom button in list tool bar and image button

Description is available here.
Blobs, download and upload
All blob content (files) are stored in a single table. It is possible to upload and download content via UI and also API for blob handling is available directly. More information is available here.
PDF
I want also add a PDF creation. But it is not easy to find a package which works in Google App Engine. The iText looks promising. It can be reached from Jython directly - look sample.
from com.itextpdf.text import DocumentException
from com.itextpdf.text import Paragraph
from com.itextpdf.text.pdf import PdfWriter

def createPDF(var) :
  
    # step 1
    document = Document()
    b = ByteArrayOutputStream()
    # step 2
    PdfWriter.getInstance(document, b)
    # step 3
    document.open()
    # step 4
    document.add(Paragraph("Hello World!"))
    #step 5
    document.close()
    return b.toByteArray()
Practical test in Google App Engine environment: http://jythonui.appspot.com/?start=startleft.xml  -> Different lists -> Dialog with attachments -> Upload -> PDF

czwartek, 2 stycznia 2014

JavaHotel - customer/guest description improved

I deployed new version of JavaHotel application. English and Polish version is available as Google App Engine application. Also J2EE version (Tomcat and Glassfish) has been created. The main enhancement is the more extensive customer description.

Also Polish version is available having localized messages and dictionaries and some smaller improvements.

niedziela, 22 grudnia 2013

JavaHotel - reservation panel improved


New version of JavaHotel has been uploaded (U/P user/user). The main difference is improved reservation panel : more compact, better navigation and better visualization of reservation.


The main challenge I fought with was adding colspan to CellTable. After spending a lot of time trying to apply different methods I ended up with copying and pasting DefaultCellTableBuilder and adding necessary changed to the underlying algorithm.