Blog do projektu Open Source JavaHotel

czwartek, 30 maja 2013

Jython MVP framework and new widget

Introduction
I extended "check list" (grid), also grid of numbers (not only checkbox) can be created. Demo version is available here, click "Number grid".
After clicking "Check" button the Jython backing action fills the bottom row with sum of numbers in the column.
More detailed information is available here.
Sample
Declaration of number grid is very simple, just add "type" info to  "checklist" tag. Example:

<checklist id="prices" displayname="Prices" type="decimal" afterdot="2" >
 </checklist>
Example of backing Jython code is available here.
Additional feature
Unlike "check box" number grid allows error visualization. In the sample application just enter number less then -10 and click "Check". More then one cell can be marked this way.
Test
Next test case has been added to the  test suite. Test scenario is available here.
Next step
This widget will be used in the hotel application to define a price list for services offered by the hotel.

MVP Jython framework and shiro authentication

Introduction
Next step in implementing Shiro authentication for JavaHotel application. Previously I developed an administrator module to add new users, hotels and to set permissions for each user in a particular hotel. Source code is available here.
This module is available in Google App Engine environment. English version and Polish version. User/Password : admin/admin. This module uses standard text based Shiro realm.
[main]
securityManager.sessionManager.sessionValidationSchedulerEnabled = false
[users]
admin=admin
[roles]
securityManager.sessionManager.sessionValidationSchedulerEnabled is disabled because it launches a thread to control session expire time but Google App Engine does not support threads.
Security implementation
After setting hotels and users next step is implemented. User can launch an application for a particular hotel and start activity for this hotel using credential implemented before. For the time being only one functionality is implemented (hotel services).
For accessing a particular hotel URL query hotel parameter is used. Example.
http://testjavahotel.appspot.com/?hotel=hotel
http://testjavahotel.appspot.com/?hotel=hotel1
Application uses another Shiro realm for this purpose.
Shiro realm
[main]
securityManager.sessionManager.sessionValidationSchedulerEnabled = false
hRealm=com.gwthotel.auth.HotelAuthRealm
inject=com.gwthotel.hotel.server.guice.HotelAuthResources
hRealm.iRes=$inject
Test
A simple test scenario can be performed.
  1. Launch http://testjavahotel.appspot.com/?start=admin.xml
  2. Add two hotels : hotel1 and hotel2
  3. Add two users: user1 and user2 (don't forget to set a password for them)
  4. Add user1 access to both hotels and and user2 only to hotel1.
  5. Launch http://testjavahotel.appspot.com/?hotel=hotel1
  6. Make sure that user1 and user2 can logon.
  7. Launch http://testjavahotel.appspot.com/?hotel=hotel2
  8. Make sure that user1 can logon and user2 cannot.
Future
Credentials setting should be modified. The solution that administrator is setting a password is invalid. Another method should be implemented, for instance:  sending a mail containing a temporary password or URL link to set the password for the first time or after resetting the password.

Problem
This application is using two different Shiro realm. During a test I found that I cannot use SecurityUtils.getSubject because after changing the realm a next call to getSubject retrieves users from the previous realm and I was unable to overcome it. The only solution I found was to give up SecurityUtils.getSubject and build Subject directly.
 private static Subject buildSubject() {
        Subject currentUser = new Subject.Builder().buildSubject();
        return currentUser;        
    }

    private Result authenticate(SessionEntry se, String tokenS) {
        SecurityManager securityManager = constructManager(se.getRealm());
        SecurityUtils.setSecurityManager(securityManager);
//        Subject currentUser = SecurityUtils.getSubject();
//        currentUser = new Subject.Builder().buildSubject();
        Subject currentUser = buildSubject();

niedziela, 26 maja 2013

Shiro, customized realm

Introduction
Shiro is very flexible and easy to extend security framework. But creating a custom realm is not  an easy task for the beginners. After some research I created a simple Shiro project to get the gist of the problem.
  1. Authentication using standard text based realm.
  2. The same using customized realm.
  3. The same using injected realm
The source code is available here (in shape of JUnit test case)
JUnit test case
The purpose is to run the same test case but using different realms. Source code.
 private void testShiro(String realM) {
        Factory factory = new IniSecurityManagerFactory(
                realM);
        org.apache.shiro.mgt.SecurityManager securityManager = factory
                .getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        ...........
        test scenario
        ...........


    @Test
    public void test() {
        testShiro("classpath:shiro.ini");
    }

    @Test
    public void test1() {
        testShiro("classpath:custom.ini");
    }

    @Test
    public void test2() {
        testShiro("classpath:inject.ini");
    }

Important: Although test, test1 and test2 are included in one test suite every test should be performed independently. This is because the next test utilize the realm created in the previous test if run inside the same JVM. I did not find a simple way to overcome it.
Standard text based realm
shiro.ini
[users]
root = secret, admin
guest = secret, welcome
Customized realm
custom.ini
[main]
myRealm=com.custom.realm.MyRealm
com.custom.realm.MyRealm
Customized realm with injection
This example is a little more complicated because mini framework has been created. The "framework" contains custom realm and interface.

package com.custom.nextrealm;

import java.util.List;

public interface InjectCredentials {

    String getPerson();
    
    String getPassword();
    
    List getRoles();

}
The user can customize this customized realm by implementing this interface and providing login name, password and list of roles without bothering about all others details. The example of this customization for the purpose of the test :
inject.ini
[main]
myRealm=com.custom.nextrealm.MyRealm
inject=com.custominject.CustomCredentials
myRealm.iCrede=$inject
com.custominject.CustomCredentials

package com.custominject;
import java.util.ArrayList;
import java.util.List;

import com.custom.nextrealm.InjectCredentials;

public class CustomCredentials implements InjectCredentials {

    @Override
    public String getPerson() {
        return "guest";
    }

    @Override
    public String getPassword() {
        return "secret";
    }

    @Override
    public List<String> getRoles() {
        List<String> roles = new ArrayList<String>();
        roles.add("welcome");
        return roles;
    }

}

sobota, 11 maja 2013

Glassfish, EJB, access to

Introduction
I'm planning to prepare a modular version of my JavaHotel application having data access logic hidden in a stateless EJB but creating a simple EJB took me more time that I expected. On one hand it should be simple and other hand (particularly after reading this web page)  it is pretty complicated. So I created a simple Eclipse project showing all important points. Code is available here. The purpose is:

  • Create EJB stateless bean.
  • Access to this bean from standalone Java application to perform JUnit tests.
  • Access to this bean from another Web component.
  • Share common definition without duplicating code.
Shared code
I created Eclipse general (not Java) project being a placeholder for common definition. By virtue of Eclipse "Link source" option this code can be shared between other projects. This project contains above all the interface with business logic implemented by EJB. It is pure  Java interface without any EJB annotation stuff. This share code contains also ServiceLocator class resolving access to EJB.

package com.sample.ejbcalc;

public interface IHelloCalc {

    String getHello();

    int add(int elem1, int elem2);

}

package com.sample.ejblocator;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.sample.ejbcalc.IEJBName;
import com.sample.ejbcalc.IHelloCalc;

public class EJBSampleLocator {
    
    public static IHelloCalc construct() throws NamingException {
        InitialContext ctx = new InitialContext();
        Object remoteObj = new InitialContext().lookup(IEJBName.JNDIRemote);
        IHelloCalc inter = (IHelloCalc) remoteObj;
        return inter;
    }

}

Bean implementation
Source code is available here.

package com.ejbcalc.impl;

import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateless;

import com.sample.ejbcalc.IEJBName;
import com.sample.ejbcalc.IHelloCalc;

/**
 * Session Bean implementation class CalcImpl
 */
@Stateless
@EJB(name = IEJBName.JNDIRemote, beanInterface = IHelloCalc.class)
@Remote
public class CalcImpl implements IHelloCalc {

    @Override
    public String getHello() {
        return "Hello, I'm your Calculator";
    }

    @Override
    public int add(int elem1, int elem2) {
        return elem1 + elem2;
    }

}
Pay attention to all  annotation stuff.
Standalone JUnit Java application
Source code is available here. Important (Glassfish). It is necessary to add gf-client.jar to classpath. This JUnit uses EJBSampleLocator utility from shared code.

import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.*;

import com.sample.ejbcalc.IHelloCalc;
import com.sample.ejblocator.EJBSampleLocator;


public class TestEJB {
    
    private static IHelloCalc i; 

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        i = EJBSampleLocator.construct();
    }

    @Test
    public void test1() {
        assertEquals("Hello, I'm your Calculator",i.getHello());
    }

    @Test
    public void test4() {
        assertEquals(4,i.add(2, 2));
        assertFalse(i.add(2, 2) == 5);
        assertEquals(2,i.add(2, 0));
        assertEquals(2,i.add(0, 2));
        assertEquals(-1,i.add(2, -3));
    }

}
Web component accessing EJB
Last (but not least) Web component. Source code is available here. One servlet reuses common ServiceLocator (like standalone application). But it is also possible to use @EJB annotation and Glassfish  injects EJB directly.

package com.ejbjsp.servlet;

import java.io.IOException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sample.ejbcalc.IHelloCalc;

@WebServlet("/Servlet2")
public class Servlet2 extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @EJB
    private IHelloCalc i;

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        response.getOutputStream().println("<h1>
 I'm Servlet 2 </h1&gt;
Bean greetings " + i.getHello() + "</pre&>
");
        response.getOutputStream().println("<br />
<h1>
 Ask Bean. What is 2 + 2 ? Bean's advice: " + i.add(2, 2) + " ! </h1>
");
        response.getOutputStream().flush();
    }

}

czwartek, 9 maja 2013

MVP framework, application and localization

Introduction
Several new features have been added to my MVP framework.
Localization
It is possible to create a fully localized application. Some localized message are framework embedded (for instance messages like: Yes, No, Accept, Resign) and it is possible also to create application specific messages.
More detailed description is available here.
Example of localized application (Google App  Engine).
English (default)
Polish
In both cases U/P is admin/admin
Check list widget utilization
In application available from above a check list widget is used in order to specify permission for the specific user in the specific hotel.
Development/production
The purpose is to develop Web application business logic only in Jython code without recompiling and redeploying the application. It means that during development every request should read fresh copy of jython code and dialog XML format. But of course it should be avoided in production code because it means significant reduction in performance. So development mode is introduced with the following features:
  1. Jython code, XML dialog and message bundles outside java class loader to avoid constantly republishing application to application server (when Eclipse project is open)
  2. No caching, just load resources directly form file system.
  3. Restart Jython with every request
  4. Every request takes a new copy of bundle messages.
Start of Java Hotel development
The application above is the first step in creating Java Hotel application. So far simple administration part is created - allows defining hotels, user and permissions.
Full source code of Java Hotel application created so far is available here. Also not Google App Engine (JPA based) version has been created.
Next step
Authentication to Java Hotel application using realm created in Administrative part described above.

środa, 1 maja 2013

Jython framework and new widget

Introduction
I added new widget to my MVP Jython framework. The purpose is to handle set of checking like that:


It is a matrix of logical values. It can be used like in the example above : to set permissions for a given user in the list of  hotels (or any other objects). The same user can have different permission in every hotel. Lines (rows) are hotels and columns are permissions. Of course - it is a matter of opinion if it were better to have hotels as lines and permissions as columns or opposite. The crux of the matter is to have the 'lines'/'columns' defined programmatically (dynamically) - not statically in the dialog definition.
Implementation
Sample implementation (Google App Engine application) is available here. Click "Check list" button at the bottom. Check/uncheck matrix elements and click "Check". The current values are sent to the Jython code in the background and two values in the upper half are set.
Defining check list in the dialog is very simple - just add checklist tag like in this sample. More than one check list is allowed. Handling values in the backing Jython code is unfortunately more complicated. We have to support three scenarios.
  • Defining lines and columns for the first time.
  • Setting values
  • Getting values.
A pretty complicated data structure is used to accomplish the task. It is described here. A sample Jython code is available here.
Future
  • It is possible to implement a matrix of number (and any other data types) but I can hardly find any use case which can implement it. 
  • Error messages applied directly to the matrix. For instance message like "Checking here is not allowed" in the direct matrix position.
Next steps
I will try to implement the beginning of my new hotel management application. It will be administrative part: defining of hotels, user and permission of user in the particular hotel.  Then implement this solution as a realm for 'Shiro' to implement security for a hotel management (not administrative).