2010-11-30
Photos of the Grand Canyon and Antelope Canyon
I have just uploaded photos of the Grand Canyon and the Antelope Canyon.
2010-11-22
Getters called multiple times in JSF
In JSF, getters of your beans might be called multiple times per request - it’s a fact. Therefore making a data source call from the getter will have a negative impact on your performance.
Suppose you have a page with a form on it. The user fills and submits the form. There are two scenarios possible - submit success or failure. The expensive call could be acquiring a list of options to choose from on the form.
For these two scenarios putting the expensive database call in the constructor or getter will not work. You will either get too many calls or too few.
And here is the solution.
This part does the trick:
Interested in how to inject FacesContext?
You can download sample code (a Maven app) that works on JBoss 6 M5.
Suppose you have a page with a form on it. The user fills and submits the form. There are two scenarios possible - submit success or failure. The expensive call could be acquiring a list of options to choose from on the form.
- The user opens the page.
- Make just one expensive database call. I.e. don’t make the same call twice.
- The user fills and submits the form.
- Display the success page, do not make the expensive database call.
- The user opens the page.
- Make just one expensive database call. I.e. don’t make the same call twice.
- The user fills and submits the form.
- Validation error occurs. Return to the form page and make the expensive call (to reload the list of options, for instance).
For these two scenarios putting the expensive database call in the constructor or getter will not work. You will either get too many calls or too few.
Solution
And here is the solution.
package me.m1key.sample.singlecall; import javax.enterprise.context.RequestScoped; import javax.faces.context.FacesContext; import javax.inject.Inject; import javax.inject.Named; // ... @Named @RequestScoped public class UserBean { @Inject private FacesContext facesContext; public List<String> getUsernames() { if (facesContext.getRenderResponse()) { System.out.println("Expensive call..."); } List<String> usernames = new ArrayList<String>(); usernames.add("Michal"); usernames.add("Ilinka"); return usernames; }
This part does the trick:
if (facesContext.getRenderResponse()) { // Expensive stuff }
Interested in how to inject FacesContext?
You can download sample code (a Maven app) that works on JBoss 6 M5.
Labels:
Java,
JSF,
Programming
2010-11-20
JSF: Inject FacesContext
In JSF, the standard way of accessing FacesContext is through a static call:
Static calls defy the purpose of OO programming, make unit testing hard, and you have to create a local variable.
Now, with the dawn of JEE6 and dependency injection you would like to do just that:
But it doesn’t work. Here is some explanation why.
The solution is to use Seam Faces. Seam Faces allow you to access FacesContext, ExternalContext and NavigationHandler without having to make static calls.
Here’s how you can add it to your project:
And it just works! Of course your server must support CDI.
Obviously, the tests require a bit of clumsy boilerplate. If you find it confusing, you can read more about unit testing with Arquillian.
You can download sample code (a Maven app) that works on JBoss 6 M5.
FacesContext context = FacesContext.getCurrentInstance();
Static calls defy the purpose of OO programming, make unit testing hard, and you have to create a local variable.
Now, with the dawn of JEE6 and dependency injection you would like to do just that:
@Inject private FacesContext facesContext;
But it doesn’t work. Here is some explanation why.
The solution
The solution is to use Seam Faces. Seam Faces allow you to access FacesContext, ExternalContext and NavigationHandler without having to make static calls.
Here’s how you can add it to your project:
<dependency> <groupId>org.jboss.seam.faces</groupId> <artifactId>seam-faces</artifactId> <version>3.0.0.Alpha3</version> </dependency>
And it just works! Of course your server must support CDI.
Unit testing
Obviously, the tests require a bit of clumsy boilerplate. If you find it confusing, you can read more about unit testing with Arquillian.
package me.m1key.sample.singlecall; import static org.junit.Assert.assertEquals; import java.io.IOException; import javax.inject.Inject; import org.jboss.arquillian.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.shrinkwrap.api.ArchivePaths; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.shrinkwrap.impl.base.asset.ByteArrayAsset; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(Arquillian.class) public class UserBeanTest { @Deployment public static JavaArchive createTestArchive() throws IllegalArgumentException, IOException { return ShrinkWrap.create("test.jar", JavaArchive.class) .addManifestResource(new ByteArrayAsset(new byte[0]), ArchivePaths.create("beans.xml")).addClasses( UserBean.class, MockFacesContext.class); } @Inject private UserBean userBean; @Test public void thereShouldBeTwoUserNames() { assertEquals(2, userBean.getUsernames().size()); } }
Sample
You can download sample code (a Maven app) that works on JBoss 6 M5.
2010-11-18
Mercurial server on Windows with Apache
In this tutorial I will show you how to set up a Mercurial 1.7.1 server on Windows using the Apache server, version 2.2.17. I successfully verified this configuration on Windows 7 and Windows XP.
It should be fairly similar for Unix based system, but I haven’t tried that. You can obviously use a different server too.
Thanks goes to my friend Jeroen who helped me out with this.
Obviously, you need Mercurial. It’s up to you how you want to install it, but make sure that the hg command is available from command line. Use the MSI installation and it will do it for you.
I will assume you installed it to C:\Program Files\Mercurial.
The second step is to obtain and install the Apache server. You may want to install it as a service. There is a nice and simple ApacheMonitor application that will put itself in your system tray and you can control your Apache from there.
I will assume you installed it to C:\Program Files\Apache Software Foundation\Apache2.2.
For the Mercurial server to work, you need to have Python installed. The Python version must correspond to the Mercurial version. For Mercurial 1.7.1 you should get Python 2.6.
Please not that you do NOT need to set a system variable called PYTHONPATH as some tutorials suggest.
I will assume you installed your Python to C:\Python26.
Download Mercurial source for your Mercurial version and unpack it. If you are lazy, you don’t have to do it - all the necessary files are available on my website (see links below).
You need to create a project where Mercurial will store your projects. I will assume it’s C:\Projects\hg.
In the Apache htdocs folder put this file - hgweb.cgi. Get it from the Mercurial source. In another folder (I will assume it’s the Mercurial installation folder) put hgweb.config - just create it.
Please note those two files are also available for download from my website (see links below).
So if you got this file from the source, you need to make it look more or less like this one.
C:\Projects\hg is, again, where Mercurial will contain your projects. It allows anyone to push. It uses the monoblue style. Provide your email in the contact field. The last line makes SSL not compulsory to be able to push.
I didn't have to do this, but user Good reported he did and he found it on the editrocket.com site.
Search the httpd.conf file for the line
Thanks Good!
Now, for each project you will have to manually create a repository in the C:\Projects\hg folder.
Go to console, go to this folder and type hg init projectName. This will create the repository.
Launch the server and go to http://localhost/hgweb.cgi. You should now see your project listed there under projectName.
You can push and pull to http://localhost/hgweb.cgi/projectName/.
Sample hgweb.cgi (I changed the extension to .txt so that the server wouldn’t treat it as a script)
Sample hgweb.config
It should be fairly similar for Unix based system, but I haven’t tried that. You can obviously use a different server too.
Thanks goes to my friend Jeroen who helped me out with this.
Installing Mercurial
Obviously, you need Mercurial. It’s up to you how you want to install it, but make sure that the hg command is available from command line. Use the MSI installation and it will do it for you.
I will assume you installed it to C:\Program Files\Mercurial.
Installing Apache
The second step is to obtain and install the Apache server. You may want to install it as a service. There is a nice and simple ApacheMonitor application that will put itself in your system tray and you can control your Apache from there.
I will assume you installed it to C:\Program Files\Apache Software Foundation\Apache2.2.
Installing Python
For the Mercurial server to work, you need to have Python installed. The Python version must correspond to the Mercurial version. For Mercurial 1.7.1 you should get Python 2.6.
Please not that you do NOT need to set a system variable called PYTHONPATH as some tutorials suggest.
I will assume you installed your Python to C:\Python26.
Downloading Mercurial source
Download Mercurial source for your Mercurial version and unpack it. If you are lazy, you don’t have to do it - all the necessary files are available on my website (see links below).
Configuring Mercurial
- Go to your Mercurial installation directory.
- Unpack the library.zip file contents into a folder called lib. You will have to create it yoruself. In this folder the contents of the library.zip file should reside direcly, i.e. the path to for instance zipfile.pyc should be C:\Program Files\Mercurial\lib\zipfile.pyc.
- Move the C:\Program Files\Mercurial\templates folder into the new lib folder.
Creating a projects folder
You need to create a project where Mercurial will store your projects. I will assume it’s C:\Projects\hg.
Configuring Apache
In the Apache htdocs folder put this file - hgweb.cgi. Get it from the Mercurial source. In another folder (I will assume it’s the Mercurial installation folder) put hgweb.config - just create it.
Please note those two files are also available for download from my website (see links below).
hgweb.cgi
#!c:/Python26/python.exe -u # # An example hgweb CGI script, edit as necessary # See also http://mercurial.selenic.com/wiki/PublishingRepositories # Path to repo or hgweb config to serve (see 'hg help hgweb') config = "C:/Program Files/Mercurial/hgweb.config" # Uncomment and adjust if Mercurial is not installed system-wide: import sys; sys.path.insert(0, "C:/Program Files/Mercurial/lib") # Uncomment to send python tracebacks to the browser if an error occurs: import cgitb; cgitb.enable() from mercurial import demandimport; demandimport.enable() from mercurial.hgweb import hgweb, wsgicgi application = hgweb(config) wsgicgi.launch(application)
So if you got this file from the source, you need to make it look more or less like this one.
hgweb.config
[collections] C:\Projects\hg = C:\Projects\hg [web] allow_push = * style = monoblue contact = you@localhost.com push_ssl = false
C:\Projects\hg is, again, where Mercurial will contain your projects. It allows anyone to push. It uses the monoblue style. Provide your email in the contact field. The last line makes SSL not compulsory to be able to push.
httpd.conf
I didn't have to do this, but user Good reported he did and he found it on the editrocket.com site.
Search the httpd.conf file for the line
Options Indexes FollowSymLinksAdd ExecCGI to this line. The line should now look similar to the following (NOTE: there may be more options listed):
Options Indexes FollowSymLinks ExecCGINext, search for the following:
#AddHandler cgi-script .cgiUncomment this line by removing the # in front of the line, and add a .py to the end of the line. The new line should look like this:
AddHandler cgi-script .cgi .py
Thanks Good!
Creating a sample project
Now, for each project you will have to manually create a repository in the C:\Projects\hg folder.
Go to console, go to this folder and type hg init projectName. This will create the repository.
Verifying
Launch the server and go to http://localhost/hgweb.cgi. You should now see your project listed there under projectName.
You can push and pull to http://localhost/hgweb.cgi/projectName/.
Sample hgweb.cgi (I changed the extension to .txt so that the server wouldn’t treat it as a script)
Sample hgweb.config
Subscribe to:
Posts (Atom)