Saturday, February 20, 2010
Subclipse Commit Hangs, Cannot Cancel, Blocks Save
The Subversion commit takes a long time, probably due to flaky network connection (which happens often). In the meantime, you continue working and make changes. Somehow, the commit never finished, so you cancel. Alas, Subclipse cannot immediately cancel, it can only give you "Cancel Requested".
Subclipse apparently provides no clean way of stopping an SVN commit operation and restarting the commit in the case of network problems. Even worse, all your work in progress cannot be saved, since Subclipse is blocking it:
The window above has been showing in my screen for about 10 minutes now, and it will never go away anyway... until I quit Eclipse or (if I can't do that) kill Eclipse process by force.
I can't even save my files! It's very frustrating. Even if Subclipse cannot cancel SVN commit cleanly, it should allow me to at least save my files so I can restart Eclipse and try again!
Update: Submitted bug to Subclipse issue tracker
Friday, February 19, 2010
NullPointerException on JSP page on JSF+PrimeFaces
java.lang.NullPointerException
at org.primefaces.component.resources.ResourcesTag.setProperties(ResourcesTag.java:37)
at javax.faces.webapp.UIComponentClassicTagBase.findComponent(UIComponentClassicTagBase.java:614)
at javax.faces.webapp.UIComponentClassicTagBase.doStartTag(UIComponentClassicTagBase.java:1142)
at org.apache.jsp.RequiredSecurityInfo_jsp._jspx_meth_p_005fresources_005f0(RequiredSecurityInfo_jsp.java:274)
I wish the errors would be more helpful.
Solution:
When using JSP view technology, JSF tags including p:resources should be wrapped inside f:view.
Source: Problem with <p:resources/>
Wednesday, February 17, 2010
java.lang.NoClassDefFoundError: org/aspectj/lang/NoAspectBoundException
java.lang.NoClassDefFoundError: org/aspectj/lang/NoAspectBoundExceptionThe solution is:
Add the AspectJ library to the classpath.
If it's a web application, that means either:
- Add the AspectJ Runtime (aspectjrt.jar) to WEB-INF/lib, or
- In Eclipse, enable AspectJ on your project. Then open Project Properties, add the AspectJ Runtime library to Java EE Dependencies.
JSF 1.2 + JSP and Facelets error - java.lang.RuntimeException: Cannot find FacesContext
HTTP Status 500 - type Exception report message description The server encountered an internal error () that prevented it from fulfilling this request. exception org.apache.jasper.JasperException: An exception occurred processing JSP page /index.jsp at line 13 10: <%@page import="java.util.List"%> 11: <%@page import="identity.Identifiable"%> 12: <%@page import="name.Nameable"%> 13: <f:view> 14: <html> 15: <head> 16: <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> Stacktrace: org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:505) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:416) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) root cause java.lang.RuntimeException: Cannot find FacesContext javax.faces.webapp.UIComponentClassicTagBase.getFacesContext(UIComponentClassicTagBase.java:1855) javax.faces.webapp.UIComponentClassicTagBase.setJspId(UIComponentClassicTagBase.java:1672) org.apache.jsp.index_jsp._jspService(index_jsp.java:93) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) note The full stack trace of the root cause is available in the Apache Tomcat/6.0.20 logs. Apache Tomcat/6.0.20This happens because:
- I've added Facelets to the web project
- I have set up the JSF default suffix to *.xhtml and JSF view technology to Facelets
- I have a JSF+JSP page
You have to use prefix mapping for the Facelets pages in order for this to work. Leave the DEFAULT_SUFFIX with the JSF default of .jsp. Configure the Facelet's VIEW_MAPPINGS parameter:The best way is, of course... to get rid of JSP pages and use Facelets exclusively. :-)
<web-app> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.jsp</param-value> </context-param> <!-- Facelets pages will use the .xhtml extension --> <context-param> <param-name>facelets.VIEW_MAPPINGS</param-name> <param-value>*.xhtml</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> </servlet> <!-- Use prefix mapping for Facelets pages, e.g. http://localhost:8080/webapp/faces/mypage.xhtml --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> </web-app>
But at least now you know you have a choice. :-)
If you're still using JSF 1.2 I heavily recommend you to upgrade to JSF 2.0 as soon as possible. Check out the book JavaServer Faces 2.0, The Complete Reference which is a great resource on using JSF 2.0.
JSF 1.2 + PrimeFaces Web Application Tutorial using Eclipse IDE
The project will:
- Use Eclipse Java EE (aka JDT + WTP)
- Not use Maven
- Deployed on Tomcat
- Use PrimeFaces JSF component library
I know you're smart enough that this is the hard way. Considering there is AppFuse, Maven archetypes, and SpringSource Tool Suite projects templates to help you start a Java web project the Ruby on Rails way. The reason is because:
- Educational purposes
- Make it easy to depend on non-Maven libraries or our own Eclipse projects
- Create new Dynamic Web project in eclipse, select JSF 1.2.
- Download JSF-RI (Mojarra) 1.2 either manually or automatically
- Make sure to export on Java EE dependencies to get libs on WEB-INF/lib (aka compile vs provided)
- Add el-impl dependency and export. This is needed for deploying to Tomcat, not needed for Glassfish other complete Java EE containers.
- Download PrimeFaces 1.x and export
- PrimeFaces Resources Servlet
- PrimeFaces p:resources (JSF 1.x only)
- Put f:view on JSP pages (mandatory) -- see forum thread about NullPointerException on p:resources
- Beans -> faces-config.xml . Eclipse IDE helps here, but now you know annotations are much nicer.
- Download Facelets as dependency and export to WEB-INF/lib
- Configure WEB-INF/web.xml
<!-- Use Documents Saved as *.xhtml --> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param> <!-- Special Debug Output for Development --> <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param> <!-- Optional JSF-RI Parameters to Help Debug --> <context-param> <param-name>com.sun.faces.validateXml</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>com.sun.faces.verifyObjects</param-name> <param-value>true</param-value> </context-param>
- Configure WEB-INF/faces-config.xml
<application> <view-handler>com.sun.facelets.FaceletViewHandler</view-handler> </application>
- Install JBoss Tools for Facelets editor code completion and other JSF helpers.
- IF you opt for not installing JBoss Tools in the previous step:
- Configure *.xhtml to be opened with JSP Editor. Open Eclipse Preferences, go to Window > Preferences > General > Content Types: Text > JSP > Add (xhtml).
- Configure Eclipse File Type associations to open *.xhtml as JSP Editor by default, not the Doxia Xhtml editor (which is very slow and not helpful). - Create a sample page.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Facelets: Number Guess Tutorial</title> <style type="text/css"> <!-- body { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: small; } --> </style> </head> <body> <h1> <ui:insert name="title">Default Title</ui:insert> </h1> <p> <ui:insert name="body">Default Body</ui:insert> </p> </body> </html>
- Redeploy the web app!
To Do
- Add Facelets
- Add Spring
- Add JPA
- Add Spring Transactions
- Add Spring Security
- Unit Testing
Tuesday, February 16, 2010
Four Approaches of Mixins in Java with AspectJ
If you're not familiar with AOP or AspectJ, the book Aspectj in Action: Enterprise AOP with Spring Applications is an excellent resource for learning AOP.
One use case of AOP is for implementing mixins or traits. Its purpose is to introduce members aka methods, properties, and fields to an existing class, and also implement interfaces. This is called static structure weaving.
There are four approaches to do static structure weaving.
Here I list them all with their benefits and weaknesses, and conclusion of when you should use it:
1. non-AOP: proxy to interface Impl
+ weaved API completion is available from consumer object+ no need for external tool (AspectJ) nor any IDE and build configuration/plugin
+ mixin Impl can be reused like approach #3 and #4 below
- needs @Embedded for JPA
- overriden aspect methods do not take effect inside aspect methods (must take the aspect Impl as a whole)
- need to code proxy methods manually
Conclusion: just say good bye to this programming model from hell. Thank me later.
Example:
public class Note implements Nameable { @Embedded private Nameable nameable = new NameableImpl(); @Override @Transient public String getName() { return nameable.getName(); } @Override public void setName(String name) { nameable.setName(name); } @Override public boolean hasName() { return nameable.hasName(); } }
2. AspectJ-only
+ can override aspect methods at will+ no need for @Embedded for JPA
- require AspectJ IDE
+ weaved API completion is available from consumer object
Conclusion: bBest choice for developing aspects, need AspectJ IDE. Resulting classes can be used normally (even with non-AspectJ IDE), especially if you use build-time weaving.
Example class:
@NameableMixin public class Ticket { }
Example aspect:
public aspect NameableAspect { declare parents : @NameableMixin * implements Nameable; declare parents : @NameableMixin * implements NameableSupport; public String NameableSupport.name; public String NameableSupport.getName() { return name; } public void NameableSupport.setName(String name) { this.name = name; } public boolean NameableSupport.hasName() { return getName() != null && !getName().isEmpty(); } }
3. @AspectJ annotations
+ can override aspect methods at will+ no need for @Embedded for JPA
+ usable in any IDE
- weaved API completion not available from consumer object
Conclusion: if you definitely can't use AspectJ IDE, start from this so you can develop aspects fast. beware that usage from client objects is not so convenient.
Example class:
@NameableMixin2 public class Project { }Example aspect using @AspectJ notation:
@Aspect public class NameableAspect2 { @DeclareMixin("@NameableMixin2 *") public Nameable nameableMixin() { return new NameableImpl(); } }Example mixin Impl:
@Embeddable public class NameableImpl implements Nameable { private String name; @Override @Basic public String getName() { return name; } @Override public void setName(String name) { this.name = name; } @Override public boolean hasName() { return getName() != null && !getName().isEmpty(); } }Using the aspected class with typecasting: (pretty bad huh?)
Project project = new Project(); Nameable named = (Nameable)project; named.setName("Get coffee"); System.out.println(named.getName());
4. AspectJ + Impl hybrid
Hybrid here means using the exact semantics of a non-AOP approach (proxying). Implementation of the aspect is a combination of AspectJ syntax for the aspect "proxy", plus standard Java for actual mixin implementation.In essence, this is a modified approach #3 that replaces the @AspectJ-annotation aspect, with AspectJ syntax aspect to introduce interface members that delegates all calls to a separate concrete implementation (in plain Java).
+ single Impl for both non-AOP (approach #1), @AspectJ (approach #3), and hybrid (this one)
+ weaved API completion is available from consumer object
+ Impl editable from any IDE. aspect code is simple thus AspectJ IDE not so required.
+ Impl can be marked as @Embeddable, but weaved class does not need to use @Embedded
- overriden aspect methods do not take effect inside aspect methods (must take the aspect Impl as a whole)
- code twice for each method: the Impl and the aspect proxy methods
Conclusion: if you don't have AspectJ IDE and you need to access the API easily. beware that aspect methods won't be overridable. you can also start from @AspectJ annotations first then switch to this when the aspect implementation is "stable". Don't start with this approach because you'll be burdened with synchronizing the AspectJ aspect with the mixin Impl.
If you want to learn more about AspectJ and AOP in general, the book Aspectj in Action: Enterprise AOP with Spring Applications by Ramnivas Laddad has the most comprehensive coverage on this subject.
Facelets tag library not loading?
"Not working" in the sense that there are no error messages, and my PrimeFaces tags are output verbatim. In a sense, PrimeFaces became 'unresolved namespace' in my web app.
I tried turning on Facelets logging but failed (I'm not so good with java.util.logging), maybe because PDL uses a different logging configuration than the "legacy" Facelets for JSF 1.2.
After hours of research, it turned out that the problem was simple: my primefaces-2.0.0.jar file is corrupt!
I used Maven to manage dependencies and I didn't realize that it did not download successfully (blame my flaky Internet connection.)
The real problem is that Tomcat did not give any indication whatsoever that one of my JARs is corrupt. Ridiculous!
"Error: Could not open JPA EntityManager" problem on EclipseLink
HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.IntegrityException Descriptor Exceptions: --------------------------------------------------------- Exception [EclipseLink-60] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DescriptorException Exception Description: The method [_persistence_setperson_vh] or [_persistence_getperson_vh] is not defined in the object [com.googlecode.pu1.domain.PersonDetail]. Internal Exception: java.lang.NoSuchMethodException: com.googlecode.pu1.domain.PersonDetail._persistence_getperson_vh() Mapping: org.eclipse.persistence.mappings.OneToOneMapping[person] Descriptor: RelationalDescriptor(com.googlecode.pu1.domain.PersonDetail --> [DatabaseTable(PERSONDETAIL)]) Runtime Exceptions: --------------------------------------------------------- java.lang.NullPointerException javax.faces.webapp.FacesServlet.service(FacesServlet.java:325)root cause
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.IntegrityException Descriptor Exceptions: --------------------------------------------------------- Exception [EclipseLink-60] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DescriptorException Exception Description: The method [_persistence_setperson_vh] or [_persistence_getperson_vh] is not defined in the object [com.googlecode.pu1.domain.PersonDetail]. Internal Exception: java.lang.NoSuchMethodException: com.googlecode.pu1.domain.PersonDetail._persistence_getperson_vh() Mapping: org.eclipse.persistence.mappings.OneToOneMapping[person] Descriptor: RelationalDescriptor(com.googlecode.pu1.domain.PersonDetail --> [DatabaseTable(PERSONDETAIL)]) Runtime Exceptions: --------------------------------------------------------- java.lang.NullPointerException org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:382) org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371) org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:336) org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:102) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) $Proxy22.findAll(Unknown Source) com.googlecode.sandcode.helloworld.HelloWorld.getName(HelloWorld.java:29) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke(Method.java:597) javax.el.BeanELResolver.getValue(BeanELResolver.java:302) javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175) com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72) com.sun.el.parser.AstValue.getValue(AstValue.java:116) com.sun.el.parser.AstValue.getValue(AstValue.java:163) com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219) com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102) javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190) javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:178) javax.faces.component.UIOutput.getValue(UIOutput.java:168) com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205) com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:338) com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164) javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:878) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1620) javax.faces.render.Renderer.encodeChildren(Renderer.java:168) javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:848) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1613) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616) com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:380) com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:126) com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:127) com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)root cause
javax.persistence.PersistenceException: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.IntegrityException Descriptor Exceptions: --------------------------------------------------------- Exception [EclipseLink-60] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DescriptorException Exception Description: The method [_persistence_setperson_vh] or [_persistence_getperson_vh] is not defined in the object [com.googlecode.pu1.domain.PersonDetail]. Internal Exception: java.lang.NoSuchMethodException: com.googlecode.pu1.domain.PersonDetail._persistence_getperson_vh() Mapping: org.eclipse.persistence.mappings.OneToOneMapping[person] Descriptor: RelationalDescriptor(com.googlecode.pu1.domain.PersonDetail --> [DatabaseTable(PERSONDETAIL)]) Runtime Exceptions: --------------------------------------------------------- java.lang.NullPointerException org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:392) org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:151) org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:207) org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:195) org.springframework.orm.jpa.JpaTransactionManager.createEntityManagerForTransaction(JpaTransactionManager.java:400) org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:321) org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371) org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:336) org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:102) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) $Proxy22.findAll(Unknown Source) com.googlecode.sandcode.helloworld.HelloWorld.getName(HelloWorld.java:29) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke(Method.java:597) javax.el.BeanELResolver.getValue(BeanELResolver.java:302) javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175) com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72) com.sun.el.parser.AstValue.getValue(AstValue.java:116) com.sun.el.parser.AstValue.getValue(AstValue.java:163) com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219) com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102) javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190) javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:178) javax.faces.component.UIOutput.getValue(UIOutput.java:168) com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205) com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:338) com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164) javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:878) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1620) javax.faces.render.Renderer.encodeChildren(Renderer.java:168) javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:848) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1613) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616) com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:380) com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:126) com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:127) com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)root cause
Exception [EclipseLink-0] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.IntegrityException Descriptor Exceptions: --------------------------------------------------------- Exception [EclipseLink-60] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DescriptorException Exception Description: The method [_persistence_setperson_vh] or [_persistence_getperson_vh] is not defined in the object [com.googlecode.pu1.domain.PersonDetail]. Internal Exception: java.lang.NoSuchMethodException: com.googlecode.pu1.domain.PersonDetail._persistence_getperson_vh() Mapping: org.eclipse.persistence.mappings.OneToOneMapping[person] Descriptor: RelationalDescriptor(com.googlecode.pu1.domain.PersonDetail --> [DatabaseTable(PERSONDETAIL)]) Runtime Exceptions: --------------------------------------------------------- java.lang.NullPointerException org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:478) org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:406) org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:671) org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:633) org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:230) org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:368) org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:151) org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:207) org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:195) org.springframework.orm.jpa.JpaTransactionManager.createEntityManagerForTransaction(JpaTransactionManager.java:400) org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:321) org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371) org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:336) org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:102) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) $Proxy22.findAll(Unknown Source) com.googlecode.sandcode.helloworld.HelloWorld.getName(HelloWorld.java:29) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke(Method.java:597) javax.el.BeanELResolver.getValue(BeanELResolver.java:302) javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175) com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72) com.sun.el.parser.AstValue.getValue(AstValue.java:116) com.sun.el.parser.AstValue.getValue(AstValue.java:163) com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219) com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102) javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190) javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:178) javax.faces.component.UIOutput.getValue(UIOutput.java:168) com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205) com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:338) com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164) javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:878) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1620) javax.faces.render.Renderer.encodeChildren(Renderer.java:168) javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:848) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1613) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616) javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616) com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:380) com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:126) com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:127) com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)note The full stack trace of the root cause is available in the Apache Tomcat/6.0.20 logs.
Apache Tomcat/6.0.20
Although the Exception list is very long, it boils down to one thing:
The JPA entity classes should be statically woven first by EclipseLink.
During project build, EclipseLink must be configured to weave your JPA entity classes.
You can also configure EclipseLink static weaving using Maven:
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-classes</phase>
<configuration>
<tasks>
<java classname="org.eclipse.persistence.tools.weaving.jpa.StaticWeave"
classpathref="maven.runtime.classpath" fork="true">
<arg line="-loglevel FINE -persistenceinfo src/main/resources target/classes target/classes"/>
</java>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<property name="eclipselink.weaving" value="static" />
Monday, February 15, 2010
Solving Tomcat + JSF 2.0 Error: java.lang.LinkageError: loader constraint violation
The problem is simple: Tomcat ships with an old version of el-api, the Expression Language used by JSP, JSTL, and JSF.HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;" the class loader (instance of org/apache/jasper/servlet/JasperLoader) of the current class, org/apache/jsp/index_jsp, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature org.apache.jasper.servlet.JspServlet.service(JspServlet.java:275) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) root cause
java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;" the class loader (instance of org/apache/jasper/servlet/JasperLoader) of the current class, org/apache/jsp/index_jsp, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature org.apache.jsp.index_jsp._jspInit(index_jsp.java:25) org.apache.jasper.runtime.HttpJspBase.init(HttpJspBase.java:52) org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:159) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:329) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) note The full stack trace of the root cause is available in the Apache Tomcat/6.0.20 logs.
Apache Tomcat/6.0.20
JSF 2.0 uses the new Java EE 6 version that is EL 2.2. Unfortunately you can't just put the new EL libraries in your WEB-INF/lib because of Tomcat's restriction.
To fix this, you don't need to change your project.. but you need to patch your Tomcat installation:
- Delete el-api.jar from your Tomcat's lib folder.
- Get the new el-api-2.2.jar from java.net and save it as el-api.jar on the Tomcat's lib folder.
For a Maven web project, put this in your pom.xml :
<dependency> <groupId>javax.el</groupId> <artifactId>el-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>el-impl</artifactId> <version>2.2</version> <scope>runtime</scope> </dependency>You also need to use java.net's Maven repository:
<repositories> <repository> <id>java.net.m2</id> <url>http://download.java.net/maven/2</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>Related Articles:
Solving Error - log4j:WARN No appenders could be found for logger
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader). log4j:WARN Please initialize the log4j system properly.Actually it's not even a real problem, but it can be confusing at first. Understandably so because the error message doesn't give any hint over how to "initialize the log4j system properly".
Fortunately, it's very easy. Just save the following code as log4j.properties. Put it inside your classpath root that is WEB-INF/classes. If you're using Maven that would be src/main/resources.
log4j.rootLogger=info, R log4j.appender.R=org.apache.log4j.ConsoleAppender log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%-5p %-30.30c{1} %x - %m%n
Solving "JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved"
org.apache.jasper.JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:51) org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:409) org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:116) org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation(TagLibraryInfoImpl.java:315) org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:148) org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:429) org.apache.jasper.compiler.Parser.parseDirective(Parser.java:492) org.apache.jasper.compiler.Parser.parseElements(Parser.java:1439) org.apache.jasper.compiler.Parser.parse(Parser.java:137) org.apache.jasper.compiler.ParserController.doParse(ParserController.java:255) org.apache.jasper.compiler.ParserController.parse(ParserController.java:103) org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:170) org.apache.jasper.compiler.Compiler.compile(Compiler.java:332) org.apache.jasper.compiler.Compiler.compile(Compiler.java:312) org.apache.jasper.compiler.Compiler.compile(Compiler.java:299) org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:586) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:317) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)This means that Tomcat cannot find the JSTL library.
If you use Maven, simply add this dependency to your pom.xml (inside <dependencies>):
<dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency
Make sure that you use the correct taglib meta-tag :
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Exposing RESTful APIs with JAX-RS on Spring
Since JAX-RS is a standard/specification, several implementations exist:
All of them should work with Spring, making it easy for you to use Spring dependency injection and other goodies with JAX-RS methods.
Don't forget to mark the JAX-RS beans as @Scope("request") because REST APIs should be stateless.
There's nothing forbidding you to use Singleton or other scoping though.
Sending HTTP Error Response from JAX-RS Method
All you need to do is throw javax.ws.rs.WebApplicationException. You don't have to change the method signature, you can still return the normal domain class when the method is successful.
@Path("{id}") public SessionResource getSession(@PathParam("id") String id) { try { // ........... } catch (IllegalArgumentException e) { throw new WebApplicationException(e, Status.NOT_FOUND); } }That's it!
JPA Error - ClassCastException: SerialContext cannot be cast to DataSource?
[EL Severe]: 2010-02-16 04:02:45.519--ServerSession(26903574)-- java.lang.ClassCastException: com.sun.enterprise.naming.impl.SerialContext cannot be cast to javax.sql.DataSource at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:110) at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:94) at org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:162) at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:584) at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:228) at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:368) at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:151) at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:207) at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:195) at user.UserTest.setUp(UserTest.java:39) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41) at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.junit.runners.ParentRunner.run(ParentRunner.java:220) at junit.framework.JUnit4TestAdapter.run(JUnit4TestAdapter.java:39) at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:422) at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:931) at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:785)I solved this problem by removing the non-jta-data-source in the persistence.xml below:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="PragmaticDciPU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>user.internal.UserMixin</class> <non-jta-data-source /> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="eclipselink.ddl-generation" value="create-tables"/> <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/> <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost/pragmaticdci"/> <property name="javax.persistence.jdbc.user" value="app"/> <property name="javax.persistence.jdbc.password" value="app"/> </properties> </persistence-unit> </persistence>
Persisting Qi4j Transient Composites using JPA
Qi4j is a framework for domain driven development aka composite-oriented programming in Java. If that's still not enough buzzwords for you, Qi4j allows you to implement Data-Context-Interaction (DCI) architecture the same way Spring Web MVC allows you to implement MVC.
Fast forward to the current results, what I get is this error:
Testcase: createOne(user.UserTest): Caused an ERROR Object: org.qi4j.runtime.composite.TransientInstance@8fa0f0 is not a known entity type. java.lang.IllegalArgumentException: Object: org.qi4j.runtime.composite.TransientInstance@8fa0f0 is not a known entity type. at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4147) at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:368) at user.UserTest.createOne(UserTest.java:57)In short, I was trying to persist a Qi4j Transient Composite object using JPA. Transient Composites are the simplest composite objects in Qi4j, I thought it may work.
But it won't, because JPA expects an entity class (the closest to that would be the a UserMixin class), not a TransientInstance class (which is Qi4j implementation detail).
Here's the test code:
// test/user/UserTest.java package user; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.junit.Test; import org.qi4j.bootstrap.AssemblyException; import org.qi4j.bootstrap.ModuleAssembly; import org.qi4j.test.AbstractQi4jTest; import static org.junit.Assert.*; public class UserTest extends AbstractQi4jTest { EntityManager em; public void assemble(ModuleAssembly module) throws AssemblyException { module.addTransients(UserEntity.class); } @Override public void setUp() throws Exception { super.setUp(); EntityManagerFactory emf = Persistence.createEntityManagerFactory("PragmaticDciPU"); assertNotNull(emf); em = emf.createEntityManager(); assertNotNull(em); } @Override public void tearDown() throws Exception { if (em != null) { em.close(); } super.tearDown(); } @Test public void createOne() { UserEntity user = transientBuilderFactory.newTransient(UserEntity.class); user.setFirstName("Hendy"); em.getTransaction().begin(); em.persist(user); em.getTransaction().commit(); UserEntity user2 = em.find(UserEntity.class, user.getId()); assertEquals(user.getFirstName(), user2.getFirstName()); } }Here's the UserEntity composite interface:
// main/user/UserEntity.java package user; import org.qi4j.api.composite.TransientComposite; public interface UserEntity extends User, TransientComposite { }Here's the User mixin interface:
// main/user/User.java package user; import org.qi4j.api.mixin.Mixins; import user.internal.UserMixin; @Mixins(UserMixin.class) public interface User { public Long getId(); void setId(Long id); String getFirstName(); void setFirstName(String firstName); String getLastName(); void setLastName(String lastName); }And finally, the User mixin implementation:
// main/user/internal/UserMixin.java package user.internal; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import user.User; @Entity public class UserMixin implements User, Serializable { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; private String firstName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }If you're curious about the persistence unit, here is it:
<!-- WEB-INF/persistence.xml --> <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="PragmaticDciPU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>user.internal.UserMixin</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="eclipselink.ddl-generation" value="create-tables"/> <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/> <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost/pragmaticdci"/> <property name="javax.persistence.jdbc.user" value="app"/> <property name="javax.persistence.jdbc.password" value="app"/> </properties> </persistence-unit> </persistence>
Friday, February 12, 2010
Writing Facelets Composite Component in JSF 2.0
Composite components are reusable custom HTML fragments + presentation logic.
I said "easier" because in JSF 1.x it was horrible. Now it's manageable, but not necessarily easier than other frameworks, like Tapestry or Wicket. At least it can compete on a similar level.
To create a composite component, write a view using Facelets XHTML like this example:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:composite="http://java.sun.com/jsf/composite"> <composite:interface> <composite:attribute name="title" required="true" /> </composite:interface> <composite:implementation> <div style="background: red; color: yellow"> #{cc.attrs.title} </div> <div style="border: 1px solid green"> <composite:insertChildren /> </div> </composite:implementation> </html>Save the XHTML code above as resources/ezcomp/titleBorder.xhtml.
Composite components live under resources folder, and the namespace will be determined from the subfolder name.
Use the ezcomp:titleBorder component like this:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ezcomp="http://java.sun.com/jsf/composite/ezcomp"> <h:head> <title>Composite Component Demo</title> </h:head> <h:body> <ezcomp:titleBorder title="Cool stuff"> So happy to be here! </ezcomp:titleBorder> </h:body> </html>Not bad, is it? ;-)
Related posts:
RESTful GET URLs with JSF 2.0
Traditionally JSF is using POST exclusively. It was possible to use GET but in practice this required some workarounds, especially because "page load action" is not natively supported by JSF. In effect, making Ruby on Rails-style controller ridiculously hard to implement.
JSF 2.0 improves this. Let's see how it's done.
A JSF-style show entity link looks like this:
<h:commandLink action="#{campaignController.prepareView}" value="Show"/>Where CampaignController.prepareView() essentially sets the current entity bean that will be displayed by the next view:
public String prepareView() { current = (Campaign)getItems().getRowData(); selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex(); return "View"; }This works, but it's quite overkill to use HTTP POST just for showing a page of entity info. To change it to GET, we use h:link :
<h:link outcome="ViewOne" value="Show Campaign"> <f:param name="campaignId" value="#{item.id}" /> </h:link>This will generate a URL like http://localhost:8080/app/faces/campaign/View?campaignId=7
We'll need to process this new parameter "campaignId", by declaring a viewParam inside f:metadata in the destination JSF view (ViewOne.xhtml):
<f:metadata> <f:viewParam name="campaignId" value="#{campaignController.campaignId}"/> </f:metadata>The campaignController.campaignId refers to a property, therefore we create the setter and getter in the controller class:
public Long getCampaignId() { if (current != null) return current.getId(); else return null; } public void setCampaignId(Long campaignId) { current = ejbFacade.find(campaignId); }That's it!
The URL is still not pretty / SEO-friendly, but for that purpose we can use PrettyFaces.
Related resources:
Solving Configuration Failed Error on JSF 2.0 + IceFaces 2.0
- icefaces.jar
- icepush.jar
- icefaces-compat.jar
- icefaces-comps-compat.jar
- krysalis-jCharts-1.0.0-alpha-1.jar
If you are getting this error:
SEVERE: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED! org.apache.commons.logging.LogFactory at org.apache.catalina.core.StandardContext.start(StandardContext.java:5216) at com.sun.enterprise.web.WebModule.start(WebModule.java:499)Backtracking above, the error log shows:
com.sun.faces.config.ConfigurationException: Source Document: jar:file:/C:/Users/ceefour/Documents/NetBeansProjects/AddressBook/build/web/WEB-INF/lib/icefaces-comps-compat.jar!/META-INF/faces-config.xml Cause: Class 'com.icesoft.faces.component.effect.ApplyEffectRenderer' is missing a runtime dependency: java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory at com.sun.faces.config.processor.AbstractConfigProcessor.createInstance(AbstractConfigProcessor.java:281) at com.sun.faces.config.processor.RenderKitConfigProcessor.addRenderers(RenderKitConfigProcessor.java:313)Which means Apache Commons Logging is needed.
To solve this problem, add commons-logging.jar into the web app classpath, and the IceFaces 2.0 web application should start successfully.
Solving EclipseLink-JPA Connection Error: User id length (0) is outside the range of 1 to 255.
User id length (0) is outside the range of 1 to 255.
It's because a non-empty username is needed for connection. However, I've put a username and the problem persists.
The solve this problem, edit META-INF/persistence.xml and add the following:
<properties> <property name="javax.persistence.jdbc.user" value="APP"/> <property name="javax.persistence.jdbc.password" value="APP"/> </properties>Change user and password to your configuration.
Note: The above works only for JPA 2.0-compliant ORM. For proprietary EclipseLink would be:
<properties> <property name="eclipselink.jdbc.user" value="APP"/> <property name="eclipselink.jdbc.password" value="APP"/> </properties>
Related resources:
Plugin Architecture for Java EE Web Applications?
Examples in the real world:
- Mozilla Firefox addons
- NetBeans modules
- Eclipse IDE plugins
- Servlet containers and WARs
The plugin system requires the capability to load a plugin WAR (a sub-WAR, perhaps) inside an already running WAR. These plugin WARs can be added, removed, configured, at runtime just like relationship of normal WARs with the container.
Java Portlets are the closest thing to a standard way of doing this. You deploy portlet WARs into a Liferay container, easy. But since we're creating something like a Portlet container, it isn't straightforward.
OSGi is probably the best bet, however it also has its own complexities and classpath model.
What's your advice?
JSF 2.0 RESTful URLs with PrettyFaces
In JSF, by default every page transition is done using HTTP POST. Even when you use JSF's GET support aka bookmarkable URLs, you still don't get the pretty SEO-friendly URLs that frameworks like Ruby on Rails generate by default.
Lucky you and me, there is a solution: PrettyFaces by OcpSoft.
Checkout the PrettyFaces slideshare presentation below on why pretty, bookmarkable, SEO-friendly URLs are important for a JSF web application; and how to do it.
What's the Java EE killer apps?
What are the Java EE killer apps, specifically the open source opens?
I definitely can think of a few well-known open source Java apps, like Liferay, Alfresco, Nuxeo...
These definitely aren't lightweight. And they're not (yet?) using the latest improvements available in Java as of 2010, not even 2009. And I shudder to think these apps being used as the reference best practices or study of Java EE's ease of development.
Can you suggest Java EE apps that are...
- "killer app" compliant, i.e. highly useful
- demonstrating practical usage of the latest Java EE technologies
- can serve as a learning tool, reading Java EE code shouldn't be that hard
- using the best design & programming practices of the Java EE community
- open source (hopefully)
Thursday, February 11, 2010
Facelets editor for Eclipse Java EE IDE ?
Is there such thing? Where?
My Google App Engine Preferred Stack
- CDI (JSR-299) for depency injection, using Weld. So apps are easily portable from/to Java EE 6.
- JPA for ORM, using GAE's recommended DataNucleus. So apps are somewhat portable. The primary key is always GAE's proprietary Key type, I wonder if this can be made somewhat more portable?
- JSF 2.0 for web framework, using Mojarra.
- PrimeFaces as the Facelets component library, as I want to try TouchFaces mobile UI. I am not fixed into a single xFaces library though. IceFaces, RichFaces, or Apache Trinidad will do just fine.
- Maven Ant Tasks for dependency management. Before GAE has decent Maven integration that allows "refresh-driven-development" aka short build-debug cycle, I'll use the standard Google App Engine for Eclipse development model, with Maven Ant Tasks to help me with JAR dependencies.
- Spring Security for authentication & authorization. Ouch... will this conflict with Weld?
Google App Engine for Java Web Development Review
Google App Engine's administration console is even not working for me. Instead of listing my apps, it continually prompts me to create an application. I have actually created a bunch of app IDs (and I can deploy my app to them).
For now, here are useful resources related to Google App Engine for Java web development:
Monday, February 8, 2010
Spring Web Flow Cheat Sheet
Based on Spring MVC, Spring Web Flow is a framework for building flow-based applications. In this Refcard, you’ll see how to add Spring Web Flow to a Spring application and define flows that initiate conversations between the application and its users.
Check out and download it here.
Thursday, February 4, 2010
What is the Best Java Web Framework?
First of all you should decide what kind of web framework are you looking for, action-based or component-based, or else.
Action-based means that the web application is fundamentally page-oriented, where HTTP requests are dispatched to a specific controller and then responded.
Component-based means that the web application is more about components than pages. You develop your web application similar to developing desktop GUI applications and Flex RIAs.
Service-oriented web applications are those that provide REST APIs and generally consume and produce JSON, XML, or Atom... not HTML. This kind of applications will be discussed in another post (remind me, please!) :-)
Here are the frameworks that I recommend you should review.
Action-based Java Web frameworks
- Spring MVC (part of Spring Framework). View technology: JSP, Velocity, Freemarker.
- Struts 2
- Grails
- JRuby on Rails
Component-based Java web frameworks
Thanks to JSF 2.0, the choice in this category is simpler. JSF 2.0 comes with built-in AJAX support, which means you not only have a choice in component libraries but can mix-and-match them if you want.- "Pure" JSF 2.0
- JSF 2.0 + IceFaces 2.0
- JSF 2.0 + RichFaces 4.0
- JSF 2.0 + PrimeFaces 2.0.
A unique feature is TouchFaces, a component library for mobile and touch devices. - JSF 2.0 + Apache Trinidad 2.0
- Apache Wicket
For the JSF 2.0 implementation you have several choices: Mojarra, Apache MyFaces.
Other considerations.
- JBoss Seam 3 (not yet released) since it has JSF 2.0 support.
Monday, February 1, 2010
Spring 3.0 vs Java EE 6 - The Review
Although they are competitors, their approach and philosophy are radically different.
Spring aims to promote best-of-breed, mix-and-match, use-only-what-you-need kind of development, and portability across all Java EE servlet web servers (most notably Apache Tomcat). That is, because the application server is Spring itself.
Java EE on the other hand, gives you the full package. It has changed a lot now with Java EE 6, in that you don't have to use all of Java EE's components to use Java EE 6. The powerful-ness of Java EE 6 comes from the standard specification of technologies, which is also its weakness: it's not really meant to be flexible.
Now when I'm talking Java EE 6, I meant the components for a web application, which are: Servlet 3.0, EJB 3.1, CDI, JSF 2.0 + Facelets, JPA.
However when I'm talking Spring, I'm mostly talking about Spring Framework, and less of the rest of the Spring Portfolio (e.g. Spring MVC, Spring Web Flow, Spring Security, etc.)
Why I mentioned that, is because there is a noticeable shift from SpringSource, the maker of Spring Framework.
In its Spring Framework version 2.5, Spring is making developers enjoy the most of Java EE 5 with:
* ability to deploy on any servlet container (since Spring "application server" is embedded)
* choice of backend implementations (JPA vs. Hibernate)
* easier to use templates to use an API (e.g. HibernateTemplate)
* enabling dependency injection to any web framework
However, recent APIs and specifications reduce the significance the above benefits of using Spring.
For example, if you're using JPA (Java Persistence API), there's not much gain of using JpaTemplate to standard JPA API. This is compared to the gain of using HibernateTemplate to Hibernate API.
In fact, JpaTemplate will make your application *less* portable. Which is what you want out of Spring. Strange, isn't it?
CDI (Java Context and Dependency Injection aka JSR 299) and Bean Validation (JSR 303) specs make this matter worse for Spring.
CDI is not only a better dependency injection than Spring, but it's a standard (Spring's XML format and annotations are always proprietary). Moreover, Spring doesn't (yet?) support CDI.
Bean Validation makes Spring MVC's validations look ancient. You can use Bean Validation with Spring using Hibernate Validator, but it's not an integral part of Spring.
Perhaps this happens because SpringSource is focusing more on its corporate strategy than the Spring philosophy.
With SpringSource always expanding its portfolio of technologies, they're now a Java application server company and infrastructure provider (with parent company VMware). Surely it's in their best interest to lock-in customers with proprietary technologies than open specifications?
Corporate politics aside, both Spring and Java EE are actually converging when you compare it with a few years ago. You can write code that work in both Spring and Java EE environments. Fortunately, the part that you still need to get specific on is only configuration... i.e. Dependency Injection.
Beyond that though, it's a completely different arena. You can assume Java EE 6 apps use JSF 2.0, but who knows what eccentric web framework is used in a Spring app?
Spring promotes Spring MVC, but it's not the only choice. Even if it's Spring MVC, there are so many ways to configure a Spring MVC app. Even more when you add Spring Web Flow. It's too flexible!
A Java EE 6 application server enables easily deployment of Java EE 6 apps. However, you don't always have to use a Java EE 6 server to use a technology from Java EE 6. For example if you use CDI, you can use an open source implementation like Weld, and run your app in Tomcat.
In the end, who will win: Spring or Java EE? Let me know what you think in the comments.
Logging to GUI by Writing Custom log4j Appender
Apache log4j is a logging implementation library for Java. It can be used directly, however to make our application more portable, we usually use logging abstraction. I recommend Apache Commons Logging for this.
The most popular logging configurations are:
- printing messages to standard console output
- appending messages to a log file
For example, you have a text box and you want to log messages to it.
Of course you can do it the old fashioned way, by getting the text box object and appending messages directly to it. But other than it is not portable, and all of your code will be dependant on that text box object.
A more robust resolution would be to use log4j's flexibility. Here I will prove to you that flexibility does not have to equal complex.
log4j since version 1.2 adds a feature that is dynamic logging configuration at runtime. We'll use this feature to add a GUI Appender to log4j. An Appender's job is to take action of a log event. In our case, displaying the log message to a text box.
See the code below:
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.Appender; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.spi.LoggingEvent; public class MainConsoleFrame extends javax.swing.JFrame { private Log log = LogFactory.getLog(MainFrame.class); private Appender guiAppender; ... public AuthoringConsoleFrame() { initComponents(); // Setup logging to GUI final MainFrame frame = this; guiAppender = new AppenderSkeleton() { @Override public boolean requiresLayout() { return true; } @Override public void close() { } @Override protected void append(LoggingEvent event) { frame.consoleMessagesArea.append(layout.format(event)); consoleMessagesArea.setCaretPosition(consoleMessagesArea.getText().trim().length() - 1); } }; guiAppender.setLayout(new PatternLayout("%5p|%40.40c|%m%n")); Logger.getRootLogger().addAppender(guiAppender); // Log like this... log.info("Hello world!"); } @Override protected void finalize() throws Throwable { Logger.getRootLogger().removeAppender(guiAppender); super.finalize(); } ... }
Please note that I skipped a lot of boilerplate code in the above.
After setting up the Appender, you probably notice that the code for logging is now very simple. It uses Apache Commons Logging which means the application will work with any logging implementation. This makes code very portable, even if you remove the textbox or move code to a different application, logging code should just work.
I hope this post is helpful to you. Let me know if you have ideas or questions.