Saturday, August 26, 2006

Grails: The DHTML JavaScript Date Picker




Grails Calendar (Date Picker) TagLib using ,The DHTML / JavaScript Calendar

http://www.dynarch.com/projects/calendar/

  1. Download jscalendar-1.0.zip from http://www.dynarch.com/projects/calendar/
  2. Extract the archive into {your-grails-app}/web-app/js/
  3. rename directory name jscalendar-1.0 to calendar.
    Ex: {your-grails-app}/web-app/js/calendar/

  4. Create a new tag library class
    source here
    see Contributed a Tag page on Grails

  5. add calendar.select=Date Select in
    {your-grails-app}/grails-app/i18n/messages.properties for locale support
  6. usage : replace <g:datePicker .... to <g:jsdatePicker ..... in edit.gsp and create.gsp



Labels: ,

Monday, August 21, 2006

Using sequence in Grails GORM



Create a "hibernate.cfg.xml" file in the "%PROJECT_HOME%\hibernate" directory of your project,
or if you always want to use sequence in Grails
Checkout Grails from the SVN repository and
you will need to customize the part of the source:

Easier Way:
(fix just one source)
Do the following change.
source code of org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder.java
at method bindSimpleId()
change

id.setIdentifierGeneratorStrategy( "native" );

to

id.setIdentifierGeneratorStrategy( "sequence" );


and add


params.setProperty(PersistentIdentifierGenerator.PK, "id");
params.setProperty("sequence", entity.getTable().getName() + "_id_seq");


just below of the


if ( mappings.getCatalogName() != null ) {
params.setProperty( PersistentIdentifierGenerator.CATALOG, mappings.getCatalogName() );
}


method bindSimpleId() will look like:

private static void bindSimpleId(GrailsDomainClassProperty identifier, RootClass entity, Mappings mappings) {

// create the id value
SimpleValue id = new SimpleValue(entity.getTable());
// set identifier on entity
entity.setIdentifier( id );
// configure generator strategy
id.setIdentifierGeneratorStrategy( "sequence" );// change here native to sequence

Properties params = new Properties();

if ( mappings.getSchemaName() != null ) {
params.setProperty( PersistentIdentifierGenerator.SCHEMA, mappings.getSchemaName() );
}
if ( mappings.getCatalogName() != null ) {
params.setProperty( PersistentIdentifierGenerator.CATALOG, mappings.getCatalogName() );
}
params.setProperty(PersistentIdentifierGenerator.PK, "id");//add here
params.setProperty("sequence", entity.getTable().getName() + "_id_seq");//add here
id.setIdentifierGeneratorProperties(params);

// bind value
bindSimpleValue(identifier, id, mappings );

// create property
Property prop = new Property();
prop.setValue(id);

// bind property
bindProperty( identifier, prop, mappings );
// set identifier property
entity.setIdentifierProperty( prop );

id.getTable().setIdentifierValue( id );

}

this always uses sequence at every tables (Domain class).
(sequence is supported on DB2,Oracle,PostgreSQL,Interbase,McKoi,SAP DB)
Check hibernate reference for more information:

hibernate mapping-declaration-id-generator




Harder way:
I fixed more code and add option like this on domain class:

def identifierGeneratorStrategy = "sequence"
//without this option domain class will use original
' IdentifierGeneratorStrategy( "native" ) '

Here is my diff:

Index: D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/GrailsDomainClassProperty.java
===================================================================
--- D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/GrailsDomainClassProperty.java (revision 1030)
+++ D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/GrailsDomainClassProperty.java (working copy)
@@ -33,6 +33,7 @@
String CLASS = "class";
String MAPPED_BY = "mappedBy";
String BELONGS_TO = "belongsTo";
+ String IDENTIFIER_GENERATOR_STRATEGY ="identifierGeneratorStrategy";

/**
* Returns the name of the property

Index: D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/GrailsDomainClass.java
===================================================================
--- D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/GrailsDomainClass.java (revision 1030)
+++ D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/GrailsDomainClass.java (working copy)
@@ -159,4 +159,10 @@
* @return A set of sub classes or an empty set if none exist
*/
public Set getSubClasses();
+
+ /**
+ * Returns the identifierGeneratorStrategy String
+ * @return identifierGeneratorStrategy
+ */
+ public String getIdentifierGeneratorStrategy();
}

Index: D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsDomainClass.java
===================================================================
--- D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsDomainClass.java (revision 1046)
+++ D:/home/aioecl/workspace/grails/src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsDomainClass.java (working copy)
@@ -62,6 +62,7 @@
private List owners = new ArrayList();
private boolean root = true;
private Set subClasses = new HashSet();
+ private String dentifierGeneratorStrategy;

public DefaultGrailsDomainClass(Class clazz) {
super(clazz, "");
@@ -84,6 +85,12 @@
if(getPropertyValue(GrailsDomainClassProperty.MAPPED_BY, String.class) != null)
this.mappedBy = (String)getPropertyValue(GrailsDomainClassProperty.MAPPED_BY, String.class);

+ if(getPropertyValue(GrailsDomainClassProperty.IDENTIFIER_GENERATOR_STRATEGY, String.class) != null)
+ this.dentifierGeneratorStrategy =
+ (String)getPropertyValue(
+ GrailsDomainClassProperty.IDENTIFIER_GENERATOR_STRATEGY, String.class);
+
+
Class belongsTo = (Class)getPropertyValue(GrailsDomainClassProperty.BELONGS_TO, Class.class);
if(belongsTo == null) {
List ownersProp = (List)getPropertyValue(GrailsDomainClassProperty.BELONGS_TO, List.class);
@@ -110,7 +117,8 @@
!descriptor.getName().equals( GrailsDomainClassProperty.OPTIONAL) &&
!descriptor.getName().equals( GrailsDomainClassProperty.CONSTRAINTS )&&
!descriptor.getName().equals( GrailsDomainClassProperty.MAPPED_BY ) &&
- !descriptor.getName().equals( GrailsDomainClassProperty.BELONGS_TO ) ) {
+ !descriptor.getName().equals( GrailsDomainClassProperty.BELONGS_TO ) &&
+ !descriptor.getName().equals( GrailsDomainClassProperty.IDENTIFIER_GENERATOR_STRATEGY )) {


GrailsDomainClassProperty property = new DefaultGrailsDomainClassProperty(this, descriptor);
@@ -498,5 +506,9 @@

public Set getSubClasses() {
return this.subClasses;
+ }
+
+ public String getIdentifierGeneratorStrategy() {
+ return this.dentifierGeneratorStrategy;
}
}

Index: D:/home/aioecl/workspace/grails/src/persistence/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java
===================================================================
--- D:/home/aioecl/workspace/grails/src/persistence/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java (revision 1101)
+++ D:/home/aioecl/workspace/grails/src/persistence/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java (working copy)
@@ -250,4 +250,10 @@
public boolean isRoot() {
return getClazz().getSuperclass().equals(Object.class);
}
+
+
+ public String getIdentifierGeneratorStrategy() {
+ // TODO Should i return some?
+ return "";
+ }
}

Index: D:/home/aioecl/workspace/grails/src/persistence/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java
===================================================================
--- D:/home/aioecl/workspace/grails/src/persistence/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java (revision 1101)
+++ D:/home/aioecl/workspace/grails/src/persistence/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java (working copy)
@@ -453,7 +453,7 @@

LOG.info( "[GrailsDomainBinder] Mapping Grails domain class: " + domainClass.getFullName() + " -> " + root.getTable().getName() );

- bindSimpleId( domainClass.getIdentifier(), root, mappings );
+ bindSimpleId( domainClass.getIdentifier(), root, mappings ,domainClass.getIdentifierGeneratorStrategy());
bindVersion( domainClass.getVersion(), root, mappings );

root.createPrimaryKey();
@@ -649,16 +649,23 @@
* @param entity
* @param mappings
*/
- private static void bindSimpleId(GrailsDomainClassProperty identifier, RootClass entity, Mappings mappings) {
+ private static void bindSimpleId(GrailsDomainClassProperty identifier, RootClass entity,
+ Mappings mappings,String identifierGeneratorStrategy) {

// create the id value
SimpleValue id = new SimpleValue(entity.getTable());
// set identifier on entity
entity.setIdentifier( id );
// configure generator strategy
- id.setIdentifierGeneratorStrategy( "native" );
+ if(identifierGeneratorStrategy!=null &&
+ identifierGeneratorStrategy.equalsIgnoreCase("sequence") ){
+ id.setIdentifierGeneratorStrategy( "sequence" );
+ }else{
+ id.setIdentifierGeneratorStrategy( "native" );
+ }

Properties params = new Properties();
+

if ( mappings.getSchemaName() != null ) {
params.setProperty( PersistentIdentifierGenerator.SCHEMA, mappings.getSchemaName() );
@@ -666,6 +673,11 @@
if ( mappings.getCatalogName() != null ) {
params.setProperty( PersistentIdentifierGenerator.CATALOG, mappings.getCatalogName() );
}
+ if(identifierGeneratorStrategy!=null &&
+ identifierGeneratorStrategy.equalsIgnoreCase("sequence")){
+ params.setProperty(PersistentIdentifierGenerator.PK, "id");
+ params.setProperty("sequence", entity.getTable().getName() + "_id_seq");
+ }
id.setIdentifierGeneratorProperties(params);

// bind value





ugly code..... :(
Maybe there is more better way to do this ..

at your own risk........ :)

Labels:

Thursday, August 10, 2006

Ruby on Railsに危険なセキュリティ・ホール

Ruby on Rails 1.1.4以前(1.1.4を含む)に危険なセキュリティ・ホールが見つかったらしい。
対策=>修正版であるバージョン1.1.5にアップデート

なお、詳細は非公表・・・・・え。。

セキュリティー関係ないが、Grailsは、SiteMeshの問題あるし・・・(この話は長くなる)・・・有る程度は、自分で直せるようにしておかないと、仕事で使えないか・・。
ただ、Grailsの場合は、Spring、Hibernate、SiteMeshにセキュリティーホールが有った場合も危険なので、その辺も完全安定するまでは、理解しておかないと。

フレームワーク使うときは、ちゃんと自分でもセキュリティーチェックを忘れないようにしよう^^;

Labels:

Thursday, August 03, 2006

Grails 0.2.1 公開

Grails 0.2 のいろいろ修正版
Grails 0.2.1が公開されました。
翻訳は、進んでません・・・

Labels: