GWT 2.5 easy Bean validation

The goal of this paper is to setup quickly and smoothly a clean validation process on your DTO. It shows an easy setup using GIN and GWT-Dispatch. An Intro is also available here Gwt 2.5 Validation Intro

The needed libraires to start are: Javax validation (Api), Hibernate validators (Sources and Implementation) and Slf4j (logger).
For the next step we are going to build a custom annotation which will be use into our gwt-dispatch actions:
Here the code for custom validator and his annotation:

@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = RequiredValidator.class)
public @interface Required {
    String message() default "Value is required";
    Class[] groups() default {};
    Class[] payload() default {};
}

 

public class RequiredValidator implements ConstraintValidator {
    @Override
    public void initialize(Required constraintAnnotation) { }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return (!Strings.isNullOrEmpty(value));
        // use Guava strings to check null or empty value
    }
}

Now we can use our required annotation into our action (There is also a possibility to use more than one annotation on our field):

public class SendMailAction extends ActionImpl {
    @Required
    private String email;
  ...
    private SendMailAction(String email) {
       this.email = email;
    }
  ...
  // add accessors
}

To complete module settings we need a validator factory for the module like it is shown into the Gwt Devguide:

public final class ClientValidatorFactory extends AbstractGwtValidatorFactory {

    // Syntax for multiple class:  @GwtValidation({action1.class, action2.class})
    @GwtValidation(SendMailAction.class)
    public interface GwtValidator extends Validator {
    }
    @Override
    public AbstractGwtValidator createValidator() {
        return GWT.create(GwtValidator.class);
    }
}

Now we are going to write a generic constraint validation manager which will be provided using Gin Injector. Here it is :

public class ClientValidation extends Validation {
    private Validator validator;
    private Set<ConstraintViolation> constraintViolations;

    public ClientValidation() {
        this.validator = buildDefaultValidatorFactory().getValidator();
    }
    public Set<ConstraintViolation> getConstraintViolations(Object object) {
        this.constraintViolations = validator.validate(object);
        return constraintViolations;
    }
    public String getPrimaryMessage() {
        return constraintViolations.iterator().next().getMessage();
    }
}

Finally we can configure one single instance into our module:

...
bind(ClientValidation.class).in(Singleton.class);

and use it everywhere on client side with @Inject:

if (!clientValidation.getConstraintViolations(new sendMailAction(email)).isEmpty()) {
            alert(clientValidation.getPrimaryMessage());
} else {
    // do something
}

Thanks to the GWT team for those enhancements for client side validation.

, ,

Leave a comment

Securing Spring Faces (Webflow 2 + Spring Security 3) application.

The post is for people who are using Spring Faces and need basic security aspects.

Update your spring faces dependency in the pom.xml if your project is a maven one :
There is a bug in the 2.3.0 Release between the flow executor and phase listener. This is important because our login page is a facelet which is not in a flow.

<dependency>
	<groupId>org.springframework.webflow</groupId>
	<artifactId>spring-faces</artifactId>
	<version>2.3.1.BUILD-SNAPSHOT</version>
</dependency>

Add context security file to the configuration with this content :

<security:http auto-config="true">
		<security:intercept-url pattern="/views/**" access="ROLE_USER"/>
		
		<security:form-login 
			login-processing-url="/j_spring_security_check"
			login-page="/" authentication-failure-url="/"
			default-target-url="/flowprocess/shopping" />
			
		<security:logout/>
	</security:http>
	
	<security:user-service id="userService">
    		<security:user name="guest" password="guest" authorities="ROLE_USER"/>
  	</security:user-service>
	
	<security:authentication-manager>
		<security:authentication-provider user-service-ref="userService"/>
	</security:authentication-manager>

Configuring security into webflow in 2 steps:

1 – Adding secure flow context listener into the configuration file as shown below :

<beans:bean id="securityFlowExecutionListener" class="org.springframework.webflow.security.SecurityFlowExecutionListener" />

<beans:bean id="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener"/>

<flow-executor id="flowExecutor">
	<flow-execution-listeners>
		<listener ref="facesContextListener"/>
		<listener ref="securityFlowExecutionListener"/>
	</flow-execution-listeners>
</flow-executor>

2 – Configure the flow to check access and authorizations before runing by adding the secure tag into the flow.xml file:

<flow start-state="identifyCustomer" xmlns="http://www.springframework.org/schema/webflow"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/webflow

http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

<secured attributes="ROLE_USER"/>
…

</flow>

Very Important Notice : If we’re using subflows in our architecture, Spring does not propagate the secured configuration to child. Secure tag must be explicitely mentionned in all our subflows. I hope this will be a fix in further releases.

Create a Spring security form-login as index page into the project.

<h:form prependId="false" >
			
	<table class="form">
		<tr>
		<td><h:outputLabel value="Identifiant: " for="j_username" /></td>
		<td><h:inputText id="j_username" required="true" value="#{authenticationBean.username}" styleClass="textInput" /></td>
		
		</tr>
		<tr>
		<td><h:outputLabel value="Mot de passe " for="j_password" /></td>
		<td><h:inputSecret id="j_password" required="true" value="#{authenticationBean.password}" styleClass="textInput" /></td>
		</tr>
	</table>
				 
	<div class="buttonContainer">
		<h:commandLink styleClass="styledButton" action="#{authenticationBean.onLogin}" value="Connect"  />
	</div>
					
</h:form>

Now the flow is secure and to execute it, user should give corrects credentials. In the next article i’ll integrate OpenID authentication.

In my project i have shopping-flow wich use customer-flow as subflow. To check the point in notice above, try to call directly the shopping/customer here unsecured access to the subflow and secured access, redirection to the login

The complete project source code is available here github

, ,

3 Comments

Build a jasper report merging pages with different format

- How to build a report with A4_portrait and Landscape pages ?

Due to the limitation of jasperReport to combine different oriented pages in one report, we are going to use Itext to create this kind of reports.

1 – In Ireport build individual templates with Portrait/Landscape orientation instead of report/sub-reports templates.

2 – Build a collection of Byte[] to save all the generated reports as shown in the code below

private List<byte[]> generateReports(Map parameters, Object objet){
    	
    	List<byte[]> reports = new ArrayList<byte[]>();
    	JasperReport jasperReport = null;
    	JasperPrint jasperPrint = null;
    	HashMap labels = new HashMap();
    	
    	try {
    	
    	JRBeanCollectionDataSource jdc = jdsfactory.createBeanCollectionDatasource(object);
    	jasperReport = (JasperReport) JRLoader.loadObject("templateFile.jasper");
    	jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, jdc);
    	reports.add(JasperExportManager.exportReportToPdf(jasperPrint));
	
	// Repeat the previous operations for all individual reports	
    		
    	} catch (Exception e) {
    		e.printStackTrace();
    	}

	return reports;
 }

3 – Call the PDF printer method to concatenate incoming files given as a collection of byte[] and build an output stream.

public static void sendConcatenatedPDFStream(List pdffiles, String fileName , HttpServletResponse response) throws Exception { 
		
		response.setContentType("application/pdf");
		response.setHeader("Pragma", "public");
		response.setHeader("Cache-Control", "max-age=0");
		response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".pdf");
		
		int totallength = 0;
		List pdfs = new ArrayList();
		for (int i=0;i&lt;pdffiles.size();i++){
			pdfs.add(new ByteArrayInputStream(pdffiles.get(i)));
		}
		BufferedOutputStream out = new BufferedOutputStream( response.getOutputStream());
		Document document = new Document();
		try {
			List readers = new ArrayList();
			int totalPages = 0;
			Iterator iteratorPDFs = pdfs.iterator();
			
			while (iteratorPDFs.hasNext()) {
				InputStream pdf = iteratorPDFs.next();
				PdfReader pdfReader = new PdfReader(pdf); readers.add(pdfReader); totalPages += pdfReader.getNumberOfPages();
			}
			
			// Create a writer for the outputstream
			PdfWriter writer = PdfWriter.getInstance(document, out);
			document.open();
			PdfContentByte cb = writer.getDirectContent(); // Holds the PDF data PdfImportedPage page;
			int currentPageNumber = 0;
			int pageOfCurrentReaderPDF = 0;
			Iterator iteratorPDFReader = readers.iterator(); // Loop through the PDF files and add to the output.
			
			while (iteratorPDFReader.hasNext()) { 
				PdfReader pdfReader = iteratorPDFReader.next(); // Create a new page in the target for each source page.
				
				while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
					document.newPage(); pageOfCurrentReaderPDF++;
					currentPageNumber++;
					page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
					cb.addTemplate(page, 0, 0); totallength += pdfReader.getFileLength(); 
					}
				pageOfCurrentReaderPDF = 0; 
			}
			document.close();
			response.setContentLength(totallength);
			out.flush();
			out.close();
			
		} catch (Exception e) { 
			e.printStackTrace(); 
		} 
}

2 Comments

Drools-guvnor manage access part-2

Using lightweight container Tomcat and Mysql server – Configuring drools-guvnor JAAS authentication module

Prequisites: Working with Drools Guvnor 5.3 deployed in Apache tomcat 6 running with Mysql 5.JDK version 1.6

0 – Deploy guvnor application with context name drools-guvnor. All users are guests then go the administration panel and set authorization for user admin or create another user with authorizations. Stop the server and we are going to enable Jaas database authentication

1 – Create authdb schema with guvnorusers table in mysql database.

CREATE TABLE guvnorusers (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);
INSERT INTO guvnorusers values (1,"admin","admin");

2 – Build a custom loginModule
Here you can find the maven source project for the custom login module drools login project sources
Just compile it and build a maven jar artifact.

3 – In %TOMCAT_HOME%/lib
Copy the loginModule exported jar file and the mysql connector jar.

4 – In %TOMCAT_HOME%/conf/context.xml, we add a resource declaration

<Resource name="jdbc/URDroolsDS" auth="Container"
	type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"
	url="jdbc:mysql://yourserveradress:3306/authdb" username="dbuser"
	password="dbuserpassword" maxActive="20" maxIdle="10" maxWait="-1" />

5 – Update %TOMCAT_HOME%/webapps/drools-guvnor/WEB-INF/components.xml
to configure our repository to use external database and security settings

<security:identity authenticate-method="#{authenticator.authenticate}"
     jaas-config-name="drools-guvnor"/>

<security:role-based-permission-resolver
     enable-role-based-authorization="true"/>

6 – Update %TOMCAT_HOME%/conf/server.xml to add a Realm declaration

<Realm className="org.apache.catalina.realm.LockOutRealm">
...
<Realm appName="drools-guvnor"
  className="com.test.droolsproto.loginmodule.realm.DroolsJaasRealm"
  dataSourceName="jdbc/URDroolsDS" localDataSource="true"/>
...
</Realm>

7 – Create a file jaasConfig on %TOMCAT_HOME%/conf with this content:
drools-guvnor{
com.test.droolsproto.loginmodule.DroolsLoginModule
required debug=true;
};

8 – Before runing Tomcat create in %TOMCAT_HOME%/bin a setenv.sh file if you running on linux or setenv.bat on windows with this content (Working on linux)

JAVA_OPTS=”-Xms128m -Xmx256m -Djava.security.auth.login.config=$CATALINA_HOME/conf/jaasConfig”
export JAVA_OPTS

Now it’s time to restart your guvnor server and check authentication!

5 Comments

Drools-guvnor manage access – part 1

Externalize business or technical rules is very important for scalable applications but the BRMS service access should be managed. guvnor provides control UI access and operations using role based authorizations.

There are several permissions types as listed in drools-guvnor reference manual.
Admin with all permissions.
Analyst or Analyst read-only: analyst permissions for a specific category.
Package admin, Package developer or Package read-only: package permissions for a specific package.

- Allow user authentication control by updating the file compenent.xml located into the server deployed folder

...
<component name="org.jboss.seam.security.roleBasedPermissionResolver>
      <property name="enableRoleBasedAuthorization">false</property>
</component>
// change false to true
...

Embedded Guvnor in Jboss server control access configuration:

Stop guvnor server if started in user guest mode and enable role based authorization.

Add drools-guvnor access policy in the file login-config.xml located in server/default/conf

<application-policy name="drools-guvnor">
<authentication>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" 
flag="required">
<module-option name="usersProperties">
props/drools-guvnor-users.properties</module-option>
<module-option name="rolesProperties">
props/drools-guvnor-roles.properties</module-option>
</login-module>
</authentication>
</application-policy>

Create properties files for users and roles with respective contents:

# A roles.properties file for UsersRolesLoginModule (drools-guvnor-roles.properties)
superuser=admin
packuser=package.admin
rulesviewer=package.readonly

# A users.properties file for UsersRolesLoginModule (drools-guvnor-users.properties)
rulesviewer=drools
packuser=proto
superuser=admin

Restart the Jboss guvnor server and log into web interface using created accounts.

Leave a comment

Drools – Guvnor: Spring integration

Using Spring 2.5, Drools-guvnor 5.0

Download Drools guvnor standalone version here jboss-drools-guvnor

Spring configuration:
– bean rulesAgent is for communication between our application and guvnor,
the Drools platform BRMS.
– bean droolsService uses rulesAgent to provide the needed service.

<bean id="rulesAgent" class="com.test.droolsproto.utils.DroolsProtoAgent"></bean>
<bean id="droolsService" class="com.test.droolsproto.serviceImpl.RuleDroolServiceImpl">
<property name="ruleAgent" ref="rulesAgent"></property>
</bean>

Create file “brmsdeployedrules.properties” for the ruleAgent:
In this file the link to use a running instance of guvnor. The package “com.test.droolsproto.rules” is an existing rules package in guvnor. DroolsDemo at the end of package value is the name of the snapshot. A snapshot in guvnor represents an image of rule’s package at specific time.

newInstance=true
url=http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/
package= com.test.droolsproto.rules/DroolsDemo
poll=30
name=droolsconfig

In the web project add drools librairies (drools-api-5.0.1, drools-core-5.0.1) and create DroolsProtoAgent class:

public class DroolsProtoAgent {
   private RuleBase rulebase;
   private StatefulSession session;
   
   private DroolsProtoAgent(){
   }
   
   public RuleBase getRulebase() {
    if (rulebase != null) return rulebase;
    else {
       RuleAgent agent = RuleAgent.newRuleAgent( "/brmsdeployedrules.properties" );
       RuleBase rulebase = agent.getRuleBase();
       return rulebase;
    }
  }
  
  public void setRulebase(RuleBase rulebase) {
    this.rulebase = rulebase;
  }
  
  public void setSession(StatefulSession session) {
    this.session = session;
  }
  
  public StatefulSession getSession() {
    if ( rulebase == null ) {
      rulebase = getRulebase();
    }
    session = rulebase.newStatefulSession();
    return session;
  }
}

Create a drools service:

public class RuleDroolServiceImpl implements RuleDroolsService {

   @Autowired
   private DroolsProtoAgent ruleAgent;

   @Override
   public String applyRule(ValueObject a, ValueObject b){

   try {
     // Load knowledge base session
     StatefulSession ksession = ruleAgent.getSession();
     ksession.startProcess("droolsProcess"); //Start a predefined process in guvnor
     
     // Insert VO as Fact
     ksession.insert(a);
     ksession.insert(b);

     ksession.fireAllRules(); //Apply rules
     return "success or specific guvnor response";
   } catch (Throwable t) {
     t.printStackTrace();
     return "failure";
   }
  }

  public DroolsProtoAgent getRuleAgent() {
   return ruleAgent;
  }

  public void setRuleAgent(DroolsProtoAgent ruleAgent) {
   this.ruleAgent = ruleAgent;
  }
}

Drools integration is complete.

Leave a comment

Birt platform

Birt is a rich open source platform for reporting task performing. I’am just working on it with usefull Eclipse IDE birt reporting tools. Easy to produce reports with chart or multiples data sources.

Good ressources to start available here: http://www.eclipse.org/birt/phoenix/

Exadel has developped an extension for Java Server Faces integration. more details on http://exadel.org/forum/jsf4birt

Leave a comment

Follow

Get every new post delivered to your Inbox.