Shervin Asgari`s blog

This blog is mainly news about Java and Computer Technology.

28. juni 2009

Iteration on password is added in JBoss Seam 2.1.2

I blogged about how you could hash your password using Seam 2.1.1 hash-user-password-in-seam-211-manually.

In the latest production release of JBoss Seam 2.1.2 and the @UserPassword annotation, an attribute of iteration is now added with a default of 1000.

We should then modify our GeneratePasswordHash method to the following:

/**
* This method will generate a hash password
*
* @param password
* - The password in cleartext
* @param salt
* - The username is used as salt
* @return - hash password based on password and username
*/
public static String generatePasswordHash(String password, String salt) throws GeneralSecurityException {
char[] passToChar;
byte[] saltToByte;
String thePassword;
try {
passToChar = password.toCharArray();
saltToByte = salt.getBytes();
AnnotatedBeanProperty<UserPassword> userPasswordProperty = new AnnotatedBeanProperty<UserPassword>(ProcessUser.class, UserPassword.class);
// Will get the hash value from annotation UserPassword in ProcessUser.class
PasswordHash.instance().setHashAlgorithm(userPasswordProperty.getAnnotation().hash().toUpperCase());
thePassword = PasswordHash.instance().createPasswordKey(passToChar, saltToByte, userPasswordProperty.getAnnotation().iterations());
return thePassword;
} finally {
// Ensure that the password is not in memory
password = null;
passToChar = null;
salt = null;
saltToByte = null;
thePassword = null;
}
}

17. juni 2009

Review of Seam 2.x Web Development

So I have read the Seam 2.x Web Development
Build Robust Web Applications with Seam, Facelets, and RichFaces, using the JBoss Application Server

This book tries to cover a very very large aspect of Seam and friends.
The book has 11 chapters and almost 300 pages. If you are new Seam, this is a great kick start. Because the book covers a huge portion of the most important aspects of Seam, plus some advanced topics such as Remoting, however I feel that the chapters are too small and that they don't give a thourough and in depth explanation. Many of the examples can be found by googling a bit and reading the documentation of Seam, but this is why it is so good to have a book covering a very large portion of it.

The RichFaces chapter could have been improved alot. Around 30 pages is hardly enough to cover this very big framework. I believe you will get more out of downloading the live examples and looking at the source code and playing around with it instead.

So to sum up, this book is good for someone new to Seam, that want an overview of most of what Seam has to offer, however I would supplement with Seam in Action to cover more ground.

20. mai 2009

New Seam book "Seam 2.x Web Development"

I have been asked to review the new book Seam 2.x Web Development from Packt Publishing

You can buy the book here
and there is also a free chapter "Developing Seam Applications" in PDF here: http://www.packtpub.com/files/seam-2-x-web-development-sample-chapter-2-developing-seam-applications.pdf

I am quite curious as to how this book is compared to Seam in Action by Dan Allen, and I will post my review here as soon as I have read the book.

26. april 2009

My JavaOne 2009 schedule

I am attending JavaOne 2009 this year, and very much looking forward to it. Only one month ahead now.
This is the schedule I have chosen:




Unfortunately, many tracks go simultaneously, but I did put the tracks that I also am interested in, in "My interest"

Tuesday, Jun 02
10:50-11:50Esplanade 307-310, Moscone Remove From Interests Ajaxifying Existing Web ApplicationsSeats Available
16:40-17:40Hall E 134, Moscone Remove From Interests Spring Framework 3.0: New and NotableSeats Available
18:00-19:00Esplanade 304-306, Moscone Remove From Interests Securing Web and Service-Oriented Architectures with Apache Axis, WSS4J, Spring, and OpenLDAPSeats Available
Wednesday, Jun 03
09:45-10:45Esplanade 307-310, Moscone Remove From Interests Extreme Google Web Toolkit: Exploring Advanced Aspects of GWTSeats Available
09:45-10:45Gateway 102-103, Moscone Remove From Interests The Modular Java? Platform and Project JigsawSeats Available
09:45-10:45Hall E 134, Moscone Remove From Interests Upgrading OSGiSeats Available
11:05-12:05Esplanade 304-306, Moscone Remove From Interests RESTful Transaction SystemsSeats Available
11:05-12:05Hall E 134, Moscone Remove From Interests Developing RESTful Web Services with the Java? API for RESTful Web Services (JAX-RS)Seats Available
11:05-12:05Gateway 102-103, Moscone Remove From Interests Modularity in the Java? Programming Language: JSR 294 and BeyondSeats Available
11:05-12:05Esplanade 307-310, Moscone Remove From Interests Ajax Performance Tuning and Best PracticeSeats Available
13:30-14:30Esplanade 307-310, Moscone Remove From Interests Creating Compelling User Experiences Seats Available
13:30-14:30Gateway 102-103, Moscone Remove From Interests "Effective Java": Still Effective After All These YearsSeats Available
Thursday, Jun 04
14:50-15:50Esplanade 305, Moscone Remove From Interests FIRST (For Inspiration & Recognition of Science and Technology): FRC-FIRST Robotic Competition Seats Available
16:10-17:10Hall E 134, Moscone Remove From Interests Keeping a Relational Perspective for Optimizing the Java? Persistence API (JPA)Seats Available

I will see you there!

6. april 2009

All unique annotations we are using in our Java EE 5 (Seam 2.1.1 GA and EJB 3 / Hibernate 3) project

Here is all the unique annoations we are using in our project (Seam 2.1.1, Hibernate, JPA, EJB 3 annotations) with a short explanation on each of them.

@AroundInvoke -- To add an interceptor to a bean, you need to write a class with a method annotated @AroundInvoke and annotate the bean with an @Interceptors annotation that specifies the name of the interceptor class.
@Asynchronous -- Specifies that the method call is processed asynchronously.
@AutoCreate -- Specifies that a component will be automatically created, even if the client does not specify create=true.
@Basic(LAZY) -- Tells the entitymanager to lazily fetch the column. This is not needed since that is the default.
@Begin(flushMode = FlushModeType.MANUAL) -- Begins a long running conversation and sets flushmode to manual. Doesnt execute operation until flush() is called.
@Begin(join = true) -- Specifies that if a long-running conversation is already in progress, the conversation context is simply propagated.
@BypassInterceptors -- disable interceptors for the component. Features such as bijection, annotated security restrictions, synchronization and others are unavailable for components marked as @ByPassInterceptors.
@CaptchaResponse(message="#{messages['verificationError']}") -- Tells what kind of message the response of the captcha should be
@CollectionOfElements --hibernate annotation that is used in conjunction with Embeddables.
@Column(length=16777215, nullable=false) -- sets an entity column to 16kb in length and not null
@Column(unique = true) -- Sets this column to be unique
@Create -- Specifies that the method should be called when an instance of the component is instantiated by Seam. Note that create methods are only supported for JavaBeans and stateful session beans.
@DataModel -- Exposes an attribute of type java.util.List to the JSF page as an instance of javax.faces.model.DataModel. This allows us to use the list in a JSF <h:dataTable> with clickable links for each row.
@DataModelSelection -- Annotation that tells Seam to inject the List element that corresponded to the clicked button
@Deprecated -- Marks the method or class as deprecated
@Documented -- Used in conjuction with creating annotations. Will make the annotation available in JavaDoc
@Duration -- Specifies that a parameter of the asynchronous call is the duration before the call is processed (or first processed for recurring calls).
@Email -- Hibernate validator for emails
@Embeddable -- Marks a class as Embeddable
@Embedded -- Classes that are Embeddable will be Embedded in the other class that uses them. IE, Address is embeddable, and is @Embedded in Person
@End -- Specifies that a long-running conversation ends when this method returns a non-null outcome without exception.
@Entity -- Marks a class as an Entity
@Expiration -- Specifies that a parameter of the asynchronous call is the datetime at which the call is processed (or first processed for recurring calls).
@Factory(value="officerAdminContact", scope=ScopeType.EVENT) -- Creates a factory with the name officerAdminContact with a scope of Event.
@Filter(name="orgFilter",condition = "organization_id = :orgid") -- Marks a class as hibernate filter with the name orgFilter, and sets the condition of the filter
@FilterDef(name="orgFilter", parameters = { @ParamDef(type="long", name="orgid")}) -- Hibernate annotation that defines a filter. The name defines which filter should be defined, and sets what kind of parameters the filter has.
@GeneratedValue -- Sets a id to be generated automatically
@Id -- Sets an attribute as Id for the entity
@In(create = true) -- Injects the field and if it is null, it will create the field
@In(required = false) -- Injects the field and tells seam that this field can be null, and will not be created if it is null
@In(required=false, scope=ScopeType.APPLICATION) -- Injects a field and sets the scope to be Application wide
@In(scope = ScopeType.BUSINESS_PROCESS) -- Injects a field and sets the scope to be BUSINESS_PROCESS
@In(value = "#{s:hasRole('sysadmin')}") -- Injects a field with an EL expression that returns true or false. In this example true if the user has role of sysadmin.
@In(value = "org.jboss.seam.bpm.jbpm") -- Injects a seam component that bootstraps a JBPM SessionFactory
@Inherited -- Indicates that an annotation type is automatically inherited. Used in conjunction with creating annotations.(?)
@Install(precedence = Install.APPLICATION) -- The @Install annotation lets you control conditional installation of components that are required in some deployment scenarios and not in others. This is useful if: *You want to mock out some infrastructural component in tests. *You want change the implementation of a component in certain deployment scenarios. *You want to install some components only if their dependencies are available (useful for framework authors). APPLICATION is the default precedence. This is appropriate for most application components.
@JoinTable(name = "ProcessUserRoles", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "roleId")) - Tells which table and what column should be joined in a table.
@Lob -- Persistence annotation that specifies that the attribute should be a large object.
@Local(ArchivingConnector.class) -- Tells the ejb which interface is the Local. An EJB can use local client view only if it is really guaranteed that other enterprise beans or clients will only address the bean within a single JVM. If this is the case, such access will be carried out with direct method calls, instead of RMI.
@Logger -- Seam's Log4J.
@ManyToOne(fetch = FetchType.LAZY, optional = true) -- Defines which filed is ManyToOne relation, with default fetch size as LAZY and that the field is optional (can be null)
@Name("lostPasswordAction") -- Creates a seam component with the name "lostPasswordAction"
@NamedQuery(name = "applicationprocess.find", query = "select ap from ApplicationProcess ap join ap.organization o where ap.name = :processName and o.name = :orgName") -- Creates a named query with the name "applicationprocess.find" which will execute the specified query. This means that you can call the query like this: entityManager.createNamedQuery("applicationprocess.find").getResultList();
@Namespace(value="http://kommuneforlaget.no/products/saksapp/process") -- Specifies the configuration namespace of a Java package containing Seam components.
@NotEmpty -- NotEmpty checks for not null and empty
@Observer("org.jboss.seam.security.loginSuccessful") -- An observer listens to the following event. In this example it will listen to successfully logins
@Officer -- Custom annotation that defines a class or a method as restricted with the role of Officer
@OneToOne(cascade = CascadeType.ALL) -- One to one relation with all cascading
@Orgadmin -- Custom annotation that defines a class or a method as restricted with the role of Orgadmin
@Out(required = false) -- Outjects the variable in the seam scope event and tell that the object can be null. Similar as request.setAttribute("bestRestaurant", restaurant);
@Out(scope = ScopeType.EVENT, required = false) -- Same as above, because the default scope in Seam is EVENT.
@Out(scope=ScopeType.SESSION, required=false) -- Same as above only the scope is set to SESSION
@Override -- Marks a method as Override. This tells the compiler that this method should override a parent method inherited.
@Parent -- A hibernate annotation that reference the property as a pointer back to the owner (generally the owning entity)
@Pattern(regex="\\D*-\\D+") -- Hibernate validator that checks the value with a regex pattern
@PermissionCheck("upgrade") -- Override the default permission action name (which is the lower case version of the annotation name) with another value. Used in conjuction with custom annotations.
@PostConstruct -- javax.annotation.PostConstruct. Used on a method that needs to be executed after dependency injection is done to perform any initialization. Only one method can be annotated with this annotation. The method MUST NOT have any parameters except in the case of EJB interceptors in which case it takes an InvocationC ontext object as defined by the EJB specification. The return type of the method MUST be void. The method MUST NOT throw a checked exception. The method on which PostConstruct is applied MAY be public, protected, package private or private. The method MUST NOT be static except for the application client. If the method throws an unchecked exception the class MUST NOT be put into service except in the case of EJBs where the EJB can handle exceptions and even recover from them.
@PrePersist -- JPA annotation that will be called right before a persist is done. Similar annotations are: PostPersist, PreUpdate, PostUpdate, PreRemove, PostRemove and PostLoad.
@RaiseEvent("templateHandler.pdf") - If a method is annotated with @RaiseEvent, it will raise an event with the name "templateHandler.pdf" after the method is finished.
@RequestParameter -- Specifies that a component attribute is to be injected with the value of a request parameter. Basic type conversions are performed automatically.
@Restrict("#{s:hasRole('orgadmin') or s:hasRole('sysadmin')}") -- Tells seam that the class can only be used if the role is orgadmin or sysadmin
@Retention(RUNTIME) -- Indicates how long annotations with the annotated type are to be retained. If no Retention annotation is present on an annotation type declaration, the retention policy defaults to RetentionPolicy.CLASS.
@Role(name="asyncReminderAction", scope=ScopeType.EVENT) -- Allows a Seam component to be bound to multiple contexts variables. The @Name/@Scope annotations define a "default role". Each @Role annotation defines an additional role. * Name — the context variable name. * scope — the context variable scope. When no scope is explicitly specified, the default depends upon the component type.
@RoleCheck -- Meta-annotation that designates an annotation as being a role, requiring a security check prior to invoking the annotated method or class.
@RoleName -- Flags an entity field or method as representing the name of a role
@Scope(ScopeType.CONVERSATION) -- Sets the scope to be CONVERSATION
@Scope(ScopeType.EVENT) -- Sets the scope to be EVENT (default)
@Scope(ScopeType.SESSION) -- Sets the scope to be SESSION
@Startup -- Specifies that an instance of this component is created at system initialization time for an application scoped component, or when a session is started for a session scoped component. May only be applied to APPLICATION or SESSION scoped components.
@Stateless -- Component-defining annotation for a stateless session bean.
@SuppressWarnings("unchecked") -- Tells the compiler to suppress warnings of type unchecked. Normally from entityManager.createQuery().getResultList()
@Sysadmin -- Custom annotation that defines a class or a method as restricted with the role of Sysadmin
@Target({TYPE, METHOD}) -- Indicates the kinds of program element to which an annotation type is applicable.
@Temporal(TemporalType.TIMESTAMP) --JPA annotation for date attributes. This will set the timestamp on a variable automatically
@Test(dependsOnMethods = "setup") -- TestNG annotation that defines this test to be dependant on a test called setup, and cant be run until that test is finished.
@Transactional -- Specifies that a JavaBean component should have a similar transactional behavior to the default behavior of a session bean component. ie. method invocations should take place in a transaction, and if no transaction exists when the method is called, a transaction will be started just for that method.
@Transient -- Defines this field to be transient. It will not be stored or serialized.
@UniqueConstraint(columnNames = "{name,organization}") -- JPA annotation that in this case defines that the attributes name and organization together should be unique.
@UserFirstName -- Flags an entity field or method as representing the first name of a user
@UserLastName -- Flags an entity field or method as representing the last name of a user
@UserPassword(hash = "md5") --Flags an entity field or method as representing the password for a user. The hash method that is used is md5 here. However sha is more secure, and "none" is also a valid option, which will not hash anything.
@UserPrincipal --Flags an entity field or method as representing the principal (username) for a user
@UserRoles --Flags an entity field or method as representing the list of role memberships for a user
@Valid -- Hibernate validator that enables recursive validation of an associated object. If used on an field, it will check all the fields validators, ie @Valid Address address = new Address(); will check all the validators of class Adress.
@Validator --Allows a Seam component to act as a JSF validator. The annotated class must be a Seam component, and must implement javax.faces.validator.Validator.
@Version --JPA annotation that specifies the version field or property of an entity class that serves as its optimistic lock value. The version is used to ensure integrity when performing the merge operation and for optimistic concurrency control. Only a single Version property or field should be used per class; applications that use more than one Version property or field will not be portable. The Version property should be mapped to the primary table for the entity class; applications that map the Version property to a table other than the primary table will not be portable.
@WebParam(name="data") --Used with WebServices and is used to customize the mapping of a single parameter to a message part or element.
@WebService -- The purpose of this annotation is to mark an endpoint implementation as implementing a web service or to mark that a service endpoint interface as defining a web service interface. All endpoint implementation classes MUST have a WebService annotation and must meet the requirements of section 3.3 of the JAX-WS 2.0 specification.
@XmlRootElement --Maps a class or an enum type to an XML element. When a top level class or an enum type is annotated with the @XmlRootElement annotation, then its value is represented as XML element in an XML document.
//Example: Code fragment
@XmlRootElement
class Point {
int x;
int y;
Point(int _x,int _y) {x=_x;y=_y;}
}

//Example: Code fragment corresponding to XML output
marshal( new Point(3,5), System.out);

<!-- Example: XML output -->
<point>
<x>3</x>
<y>5</y>
</point>

@XmlSeeAlso -- Instructs JAXB to also bind other classes when binding this class.
Java makes it impractical/impossible to list all sub-classes of a given class. This often gets in a way of JAXB users, as it JAXB cannot automatically list up the classes that need to be known to JAXBContext.
For example, with the following class definitions:

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

The user would be required to create JAXBContext as JAXBContext.newInstance(Dog.class,Cat.class) (Animal will be automatically picked up since Dog and Cat refers to it.)
XmlSeeAlso annotation would allow you to write:
@XmlSeeAlso({Dog.class,Cat.class})
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

This would allow you to do JAXBContext.newInstance(Animal.class). By the help of this annotation, JAXB implementations will be able to correctly bind Dog and Cat.

30. mars 2009

Adding html cache on a JSF 1.2 / Seam 2.1.1 application

Adding cache in seam is very easy, and the 2.1.1 release has even made using caching easier.

It is useful to cache html typically when you have lots of hits to the database, otherwise you shouldn't use html cache.

I recently needed to read the current url, extract a part of the url, and check the database for a hit on that pattern. This was done on every request and is something that suits caching. The data I was retrieving was something that was changed very rarely thus it could also be cached infinetly. For this purpose, I have chosen the in-built treecache that ships with JBoss and Seam.

Getting the url from a JSF page can be done like this:
       
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
String uri = request.getRequestURI();
// zero so that trailing empty strings will be discarded
String[] values = uri.split("/", 0);
//Concatinate the string and create a query based on the concatinated string
Now in the xhtml page you will have to write:
<s:cache region="instructionPageFragments" key="instruction-#{instructionHandler.instructionUrl}">
#{instructionHandler.getInstruction()}
</s:cache>
Note that the key must be something unique. In this example the key value will get the current url as a key, and in our web application this is unique, thus works excellent as a key. The s:cache will use the key to retrieve the value from its HashMap.
s:cache uses pojoCache internally, but we want to configure it to use treecache and that is done in components.xml.
You do this by defining the namespace
xmlns:cache="http://jboss.com/products/seam/cache"
and then
<cache:jboss-cache-provider configuration="META-INF/treecache.xml">
Furthermore, we have defined a region on the s:cache called instructionPageFragments. This can be configured in treecache.xml where we can define timeToLive maxAgeSeconds and so on.

<region name="/instructionPageFragments" policyClass="org.jboss.cache.eviction.LRUPolicy">
<attribute name="maxNodes">0</attribute>
<attribute name="timeToLiveSeconds">0</attribute>
<attribute name="maxAgeSeconds">0</attribute>
</region>

A copy of our entire treecache.xml is here:
<?xml version="1.0" encoding="UTF-8"?>

<!-- ===================================================================== -->
<!-- -->
<!-- Sample TreeCache Service Configuration -->
<!-- -->
<!-- ===================================================================== -->

<server>

<classpath codebase="../lib" archives="jboss-cache.jar, jgroups.jar"/>


<!-- ==================================================================== -->
<!-- Defines TreeCache configuration -->
<!-- ==================================================================== -->

<mbean code="org.jboss.cache.TreeCache"
name="jboss.cache:service=TreeCache">

<depends>jboss:service=Naming</depends>
<depends>jboss:service=TransactionManager</depends>

<!--
Configure the TransactionManager
-->
<attribute name="TransactionManagerLookupClass">org.jboss.cache.JBossTransactionManagerLookup</attribute>

<!--
Isolation level : SERIALIZABLE
REPEATABLE_READ (default)
READ_COMMITTED
READ_UNCOMMITTED
NONE
-->
<attribute name="IsolationLevel">REPEATABLE_READ</attribute>

<!--
Valid modes are LOCAL
REPL_ASYNC
REPL_SYNC
INVALIDATION_ASYNC
INVALIDATION_SYNC
-->
<attribute name="CacheMode">LOCAL</attribute>

<!--
Just used for async repl: use a replication queue
-->
<attribute name="UseReplQueue">false</attribute>

<!--
Replication interval for replication queue (in ms)
-->
<attribute name="ReplQueueInterval">0</attribute>

<!--
Max number of elements which trigger replication
-->
<attribute name="ReplQueueMaxElements">0</attribute>

<!-- Name of cluster. Needs to be the same for all clusters, in order
to find each other
-->
<attribute name="ClusterName">TreeCache-Cluster</attribute>

<!-- JGroups protocol stack properties. Can also be a URL,
e.g. file:/home/bela/default.xml
<attribute name="ClusterProperties"></attribute>
-->

<attribute name="ClusterConfig">
<config>
<!-- UDP: if you have a multihomed machine,
set the bind_addr attribute to the appropriate NIC IP address -->
<!-- UDP: On Windows machines, because of the media sense feature
being broken with multicast (even after disabling media sense)
set the loopback attribute to true -->
<UDP mcast_addr="228.1.2.3" mcast_port="48866"
ip_ttl="64" ip_mcast="true"
mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
loopback="false"/>
<PING timeout="2000" num_initial_members="3"
up_thread="false" down_thread="false"/>
<MERGE2 min_interval="10000" max_interval="20000"/>
<!-- <FD shun="true" up_thread="true" down_thread="true" />-->
<FD_SOCK/>
<VERIFY_SUSPECT timeout="1500"
up_thread="false" down_thread="false"/>
<pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
max_xmit_size="8192" up_thread="false" down_thread="false"/>
<UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"
down_thread="false"/>
<pbcast.STABLE desired_avg_gossip="20000"
up_thread="false" down_thread="false"/>
<FRAG frag_size="8192"
down_thread="false" up_thread="false"/>
<pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
shun="true" print_local_addr="true"/>
<pbcast.STATE_TRANSFER up_thread="true" down_thread="true"/>
</config>
</attribute>

<!--
Whether or not to fetch state on joining a cluster
NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive.
-->
<attribute name="FetchInMemoryState">true</attribute>

<!--
The max amount of time (in milliseconds) we wait until the
initial state (ie. the contents of the cache) are retrieved from
existing members in a clustered environment
-->
<attribute name="InitialStateRetrievalTimeout">20000</attribute>

<!--
Number of milliseconds to wait until all responses for a
synchronous call have been received.
-->
<attribute name="SyncReplTimeout">20000</attribute>

<!-- Max number of milliseconds to wait for a lock acquisition -->
<attribute name="LockAcquisitionTimeout">15000</attribute>


<!-- Name of the eviction policy class. -->
<attribute name="EvictionPolicyClass"></attribute>

<!--
Indicate whether to use marshalling or not. Set this to true if you are running under a scoped
class loader, e.g., inside an application server. Default is "false".
-->
<attribute name="UseMarshalling">false</attribute>


<!-- Specific eviction policy configurations. -->
<attribute name="EvictionPolicyConfig">
<config>
<attribute name="wakeUpIntervalSeconds">120</attribute>

<!-- Cache wide default -->
<region name="/_default_"
policyClass="org.jboss.cache.eviction.LRUPolicy">
<!-- This is the maximum number of nodes allowed in this region. -->
<!-- 0 denotes no limit. -->
<attribute name="maxNodes">0</attribute>

<!-- The amount of time a node is not written to or read (in seconds) before the node is swept away.-->
<!-- 0 denotes no limit. -->
<attribute name="timeToLiveSeconds">0</attribute>

<!-- Lifespan of a node (in seconds) regardless of idle time before the node is swept away. -->
<!-- 0 denotes no limit. -->
<attribute name="maxAgeSeconds">0</attribute>
</region>

<!-- We dont have to define each region if we have default 0 values, but just incase we want to change it later -->

<!--
<region name="/instructionPageFragments" policyClass="org.jboss.cache.eviction.LRUPolicy">
<attribute name="maxNodes">0</attribute>
<attribute name="timeToLiveSeconds">0</attribute>
<attribute name="maxAgeSeconds">0</attribute>
</region>

<region name="/reviewInputPageFragments" policyClass="org.jboss.cache.eviction.LRUPolicy">
<attribute name="maxNodes">0</attribute>
<attribute name="timeToLiveSeconds">0</attribute>
<attribute name="maxAgeSeconds">0</attribute>
</region>

<region name="/actorPageFragments" policyClass="org.jboss.cache.eviction.LRUPolicy">
<attribute name="maxNodes">0</attribute>
<attribute name="timeToLiveSeconds">0</attribute>
<attribute name="maxAgeSeconds">0</attribute>
</region>
-->
</config>
</attribute>


</mbean>


<!-- Uncomment to get a graphical view of the TreeCache MBean above -->
<!-- <mbean code="org.jboss.cache.TreeCacheView" name="jboss.cache:service=TreeCacheView">-->
<!-- <depends>jboss.cache:service=TreeCache</depends>-->
<!-- <attribute name="CacheService">jboss.cache:service=TreeCache</attribute>-->
<!-- </mbean>-->


</server>

Since I want everything to be cached infinetly I have uncommented the regions out and put 0 (no limit) on the _default_ region

You can also programatically add and remove content to the cache.
@In 
private CacheProvider cacheProvider;

//Removing the cache with the region instructionPageFragments, and the key instruction-'current url'
cacheProvider.remove("instructionPageFragments", "instruction-" + url);
//Adding to the cache
cacheProvider.put("instructionPageFragments", "instruction-" + url, "This text will be cached!!");

13. februar 2009

Hash user password in Seam 2.1.1 manually without using IdentityManager

In the Seam Documentation, they give a minimal schema example of how you can create Users and Roles here: http://docs.jboss.com/seam/2.1.1.GA/reference/en-US/html_single/#d0e9178

As it is explained in the documentation, you can annotate your password with

@UserPassword(hash = "md5")
public String getPasswordHash() { return passwordHash; }
public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
You could also use
hash= "none"
which doesnt hash the password which is what I did at first. The reason why I didnt start using md5 at once is because you needed a default username and password to be able to log into your seam application. And since I was using an import.sql script that created a default user for me, I had no way of knowing how to hash the password.

So what I needed to do is manually somehow hash a password which I could put in my import.sql script, so that I could enable hashing and correctly log in to my seam application. However this was easier said then done.
I tried changing the @UserPassword(hash="md5") and try to log in, but for obvious reason the login failed, because it was expecting a hashed password.

So then I got the idea to call a method that doesn't require login, which creates a user for us, that is called from a button in the login page. However when I persisted the user, the password was saved as clear text. This baffled me, because I thought that seam would handle that automatically. But if you actually look at the user entity and the setHashPassword method, it is not annotated, and it only sets a string. So it was obvious it only persisted the password as string.
In Seam you can also use IdentityManager to create a user for you. This will perform the hashing for you. So I tried to call
identityManager.createUser("username","password","firstname","lastname");

However, identityManager requires that you are correctly Authenticated, and it threw an exception
org.jboss.seam.security.AuthorizationException: Authorization check failed for permission seam.user,create

So apparently IdentityManager requires the correct permissions, which must be set in your drools setting in security.drl, but I didn't want to do that, since that is not how I wanted to configure my seam application.

So what I did, was look in the seam source and IdentityManager class and find the exact code that performs the hashing for us, and do that manually. And this worked great. Here is the source.

public String saveProcessUser() {
// Check if a new password has been entered
if (currentUser.getPasswordHash() != null && !"".equals(currentUser.getPasswordHash())) {
if (!currentUser.getPasswordHash().equals(passwordVerify)) {
StatusMessages.instance().addFromResourceBundle("admin.wrongPassword");
return "failure";
}
}

// If passwordVerify is not empty, it generally means its a new password
if (!passwordVerify.equals("")) {
String hashPass = generatePasswordHash(currentUser.getPasswordHash(), currentUser.getUsername());
log.debug("Setting new hash password: " + hashPass);
currentUser.setPasswordHash(hashPass);
}

if (getCurrentUser().getId() != null) {
entityManager.flush();
} else {
entityManager.persist(currentUser);
}

FacesMessages.instance().addToControlFromResourceBundle("successMessage", "admin.user.saved");
return "success";
}

/**
* This method will generate a hash password
*
* @param password - The password in cleartext
* @param salt - The username is used as salt
* @return - hash password based on password and username
*/
private String generatePasswordHash(String password, String salt) {
AnnotatedBeanProperty<UserPassword> userPasswordProperty = new AnnotatedBeanProperty<UserPassword>(ProcessUser.class, UserPassword.class);
// Will get the hash value from annotation UserPassword in ProcessUser.class
String algorithm = userPasswordProperty.getAnnotation().hash();
return PasswordHash.instance().generateSaltedHash(password, salt, algorithm);
}


Note that the method saveProcessUser() is called from the user administration form, and the currentUser object is my User entity. Seam will inject all the methods for us, so we dont have to do that. So we check if the verifyPassword is set and correct and then we hash the password. If the @UserPassword is set to something other than none, then it will correctly save a user and you can finally copy the hashed password in your import.sql script.

PS: You first should have the @UserPassword(hash="none") and then go to your user registration and then just print out what the password is, and then copy that to your import.sql script. When the authentication correctly works with either md5 or sha, then you can safely add the user to the database.

About me

Mitt foto
Shervin Asgari
Java Developer currently working at Redpill Linpro
Vis hele profilen min