- I should have started using Maven earlier. If you want to manage an inhouse repository check out the Artifactory. Ill make better use of it on my next project.
- Hudson: More capable than CC, easily configurable UI, pluggable, integrates with svn, maven, ant... And don't forget to revert before update.
- HTML5 Canvas looks cool. 3D Games + Drawing tools + ?. If you haven't already check this out ; http://mrdoob.com/la
b/javascript/harmony , he also has 3d engine based on JS. I'll try this out may be do a project. - There is the Devoxx @ 15 Nov., Call for papers deadline is 6 Jun.
- Dynamic reporting with jasper reports. This guy has a clever and basic idea of how to do it. Implemented a similar thing. Plus I added annotations to format and display the data.
- Single Sign-On/Out with CAS.
- Our project is still approaching the deadline. A bit tired.
Wednesday, May 19, 2010
Status
Wednesday, March 24, 2010
Hibernate Usage Strategy
Lately I got to refresh my hibernate knowledge. On previous posts I wrote about my experience with hibernate here and how things could get tangled up trying to load objects.
When using hibernate most important decision you have to make is how you are going to manage sessions. Basically you have to choose from a method scoped (service) session or conversation scoped long running sessions. My choice is here is to use the first one. While using a conversation scoped session might be easier to programmer downside is that database access could happen anywhere on your application uncontrolled. I think that could end you up, having to track down some performance bottlenecks, plus it means having a big object (session) in memory for some time.
Strategy
Not using a conversation scoped session forces you to determine an access strategy for your lazy associations. Note that you should still use these strategies even if you are using conversation scoped session, difference is it doesn't force you to.
Using Join Fetches
Joining usually gets omitted but it's the first thing to do. If you need lazy association, of a list of results, you have to join fetch them. Query below loads the cities with its parks:
select c from City c join fetch c.parks
Of course if you need to list cities which don't have parks you have to use "left join fetch".Caching
I remember reading, probably, on hibernate reference documentation something like caching is the last thing to do for performance. Now I think that I have underestimated using second level cache. Tables that hold rarely changing data should be loaded eagerly and cached. I also use a separate select to load them. This is how I mark such fields;
1: @ManyToOne
2: @Fetch(FetchMode.SELECT)
3: CityType type;
This will force hibernate to cache the data upon first access. Using a cache will generate much smaller queries and you wont have to write huge join statements to load lazy stuff.
I'll probably do more work using cache on an clustered environment.
Monday, February 15, 2010
What I been up to last couple of weeks
Day job kept quite busy last couple of weeks. Our new project is not managed in a agile way so after some months of preparing "big docs" we have finally hit the stage of coding. Just before starting to code, we have realised that we needed to change some of the architectural decisions we assumed and do some work on our code-base. We would have done that a lot earlier probably if we were on a agile route...
IDEs
We have decided to have 5 different applications that could be plugged in and out from each-other, formed by at least three modules; ejbs, ejb clients and a gui.
I found developing an app. made up of different modules in Eclipse quite limiting. You can't configure different web.xml's or persistence.xml's for different configurations you have.
IDEA9 on the other hand, has just what I had in my mind. It has a great artifacts screen where you can control where what configuration will go, which modules compile-output will go where and what jars to copy on what directory.Things I missed from Eclipse were the subclipse and Propedit plugins. Also on IDEA the run screen strangely only had "deploy all" button. To deploy my apps. seperately I needed to use autodeploy feature or the remote server setting. IDEA9 has 30 days of free evaluation period where you can test it. For now we are still bound to Eclipse but we might choose to use IDEA in the future.
Application Server
Another major change was since we needed an Application Server for ejbs we couldnt use the developer friendly Tomcat. I had a nice experience with GlassFishV3 server while doing the JEE6 projects, but our company would probably choose BEA's Weblogic. Every AS needs some twiks. Weblogic had some class loader problem with our app. which we needed to overcome by defining a weblogic-application.xml. Details could be found here. One last thing to note is, weblogic jndi look-upsi needs the qualified class names. Like if you have a mapped name of "my/MyService" you have to look it up with; "my/MyService#interfaceName..."
Lookups
GUI part of our app. is made of jsf & spring. I have used the springs LocalStatelessSessionProxyFactoryBean to lookup EJB's. It does it's job but I believe it has some missing features. It would be far more efficient, while developing, if I didn't had to restart my gui after my ejb's were deployed. On that case instead of performing the lookup again spring just throws an exception, though I think I could find a solution that does that.
Mentoring
Thats what I do mostly here. I started getting bored with that... From now on I think I will mostly just hit people behind their neck to point them to right direction.
Monday, January 11, 2010
Multipart Requests and JSF
Multipart requests are used when client needs to upload files to server. A multipart request has a different encoding and requires to be parsed.
JSF2 doesn't come with any fileupload component nor it has any support with multipart requests. A multipart request to JSF (mojarra impl. 2.0.2) just executes the 'restore view' and 'render response' phases, simply because JSF can't extract the request parameters from the multipart request.
Here is what I did to implement a file upload scenerio in JSF:
Define the view
I defined my view a form with multipart encoding and file input:
1: <h:form enctype="multipart/form-data">
2: User : <h:inputText value="#{join.userName}"/>
3: Wall : <h:inputText value="#{join.wallName}"/>
4: Avatar : <input id="avatar" name="avatar" type="file" />
5: <h:commandButton value="Login" action="#{join.create}"/>
6: </h:form>
Wrap & Parse The Request
I used commons-fileupload to parse the request and used CDI event dispatching to assign the uploaded file to beans :
1: public class MultipartRequestWrapper extends HttpServletRequestWrapper {
2:
3: private Hashtable<String, String[]> params = new Hashtable<String, String[]>();
4:
5: MultipartRequestWrapper(HttpServletRequest request, Event<FileItem> uploadEvents) {
6: super(request);
7: DiskFileItemFactory factory = new DiskFileItemFactory();
8: factory.setSizeThreshold(2097152);
9: ServletFileUpload upload = new ServletFileUpload(factory);
10: upload.setSizeMax(2097152);
11:
12: try {
13: List<FileItem> items = upload.parseRequest(request);
14: for (FileItem item : items) {
15: if (item.isFormField()) {
16: params.put(item.getFieldName(), new String[]{new String(item.get())});
17: } else {
18: uploadEvents.fire(item);
19: }
20: }
21: } catch (FileUploadException e) {
22: throw new RuntimeException(e);
23: }
24: }
25:
26: @Override
27: public String getParameter(String name) {
28: String [] values = getParameterValues(name);
29: if(values == null || values.length == 0) {
30: return null;
31: }
32:
33: return values[0];
34: }
35:
36: @Override
37: public Map<String, String[]> getParameterMap() {
38: return params;
39: }
40:
41: @Override
42: public Enumeration<String> getParameterNames() {
43: return params.keys();
44: }
45:
46: @Override
47: public String[] getParameterValues(String name) {
48: return params.get(name);
49: }
50:
51: }
Line 16 parses and extracts the request parameters and and line 8 publishes the file item to the listening beans. A simple filter checks the request and if it's a multipart request it wraps the request with this wrapper.
Monday, December 21, 2009
JSF PhaseListeners With Annotations
Although JSF 2 moved most of it's configuration to annotations still some must be made on xml's, like the phase listeners.
The most straight forward way to implement a mechanism that would enable defining them with annotations are treating phase listeners as singletons. Than we could simply annotate static methods with after phase, before phase annotations.
A second and more elegant/useful way would be to treat phases as cdi events and observe these events.
Annotating static methods
I have created @BeforePhase and @ActionPhase annotations that take phase id as parameter and mark static methods with that :
The most straight forward way to implement a mechanism that would enable defining them with annotations are treating phase listeners as singletons. Than we could simply annotate static methods with after phase, before phase annotations.
A second and more elegant/useful way would be to treat phases as cdi events and observe these events.
Annotating static methods
I have created @BeforePhase and @ActionPhase annotations that take phase id as parameter and mark static methods with that :
1: public class ActionContext extends AbstractThreadLocalMapContext {
2:
3: private static ActionContext instance = new ActionContext();
4: ...
5: @BeforePhase(CycleId.RESTORE_VIEW)
6: public static void activate() {
7: instance.setActive(true);
8: instance.setBeanStore(new ConcurrentHashMapBeanStore());
9: }
10:
11: @AfterPhase(CycleId.RENDER_RESPONSE)
12: public static void deActivate() {
13: instance.destroy();
14: instance.setActive(false);
15: instance.setBeanStore(null);
16: }
17:
18: @AfterPhase(CycleId.INVOKE_APPLICATION)
19: public static void reActivate() {
20: instance.deActivate();
21: instance.activate();
22: }
23:
24: }
Now we need a phase listener that would scan for these annotations and act as a proxy for these methods. I used the Scannotation to scan for the annotations and proxy phase listener still must be defined in faces-config.xml:
1: public class ProxyPhaseListener
2: implements PhaseListener {
3:
4: private Map<Integer, Set<Target>> afterregistry;
5: private Map<Integer, Set<Target>> beforeregistry;
6:
7: public ProxyPhaseListener() {
8: try {
9: URL ucp = new URL(ClasspathUrlFinder.findClassBase(getClass()).toString().replaceAll("%20", " "));
10: AnnotationDB db = new AnnotationDB();
11: db.setScanClassAnnotations(false);
12: db.setScanFieldAnnotations(false);
13: db.setScanParameterAnnotations(false);
14: db.scanArchives(ucp);
15: afterregistry = new HashMap<Integer, Set<Target>>();
16: beforeregistry = new HashMap<Integer, Set<Target>>();
17: Map<String, Set<String>> map = db.getAnnotationIndex();
18: registerMethods(map, afterregistry, new AfterPhaseRegisterer());
19: registerMethods(map, beforeregistry, new BeforePhaseRegisterer());
20: } catch (Exception ex) {
21: throw new RuntimeException(ex);
22: }
23: }
24:
25: public void afterPhase(PhaseEvent event) {
26: invoke(event, afterregistry);
27: }
28:
29: private void invoke(PhaseEvent event,Map<Integer, Set<Target>> registry) {
30: Set<Target> targets = registry.get(event.getPhaseId().getOrdinal());
31: if (targets != null) {
32: for (Target target : targets) {
33: target.invoke();
34: }
35: }
36: }
37:
38: public void beforePhase(PhaseEvent event) {
39: invoke(event, beforeregistry);
40: }
41:
42: public PhaseId getPhaseId() {
43: return PhaseId.ANY_PHASE;
44: }
45:
46: private void registerMethods(Map<String, Set<String>> annotationIndex,
47: Map<Integer, Set<Target>> registry,
48: PhaseRegisterer phaseRegisterer) throws ClassNotFoundException, SecurityException {
49: Set<String> classes = annotationIndex.get(phaseRegisterer.getPhaseMetaData().getName());
50: if(classes != null) {
51: for (String c : classes) {
52: Class clazz = Class.forName(c);
53: Method[] ms = clazz.getDeclaredMethods();
54: for (Method m : ms) {
55: for (Annotation an : m.getDeclaredAnnotations()) {
56: Class antype = an.annotationType();
57: if (antype.equals(phaseRegisterer.getPhaseMetaData())) {
58: phaseRegisterer.register(an, registry, m, clazz);
59: }
60: }
61: }
62: }
63: }
64:
65: }
66:
67: protected class AfterPhaseRegisterer implements PhaseRegisterer {
68: public void register(Annotation an, Map<Integer, Set<Target>> registry, Method m, Class clazz) {
69: AfterPhase ap = (AfterPhase) an;
70: Integer key = ap.value().ordinal();
71: Set<Target> value = registry.get(key);
72: if (value == null) {
73: value = new HashSet<Target>();
74: }
75: value.add(new Target(m, clazz));
76: registry.put(key, value);
77: }
78:
79: public Class<? extends Annotation> getPhaseMetaData() {
80: return AfterPhase.class;
81: }
82: }
83:
84: protected class BeforePhaseRegisterer implements PhaseRegisterer {
85: ...
86: }
87:
88: interface PhaseRegisterer {
89: void register(Annotation an, Map<Integer, Set<Target>> registry, Method m, Class clazz);
90: public Class<? extends Annotation> getPhaseMetaData();
91: }
92:
93: protected class Target {
94: private Method method;
95: private Class clazz;
96:
97: public Target(Method method, Class clazz) {
98: this.method = method;
99: this.clazz = clazz;
100: }
101:
102: private void invoke() {
103: try {
104: method.invoke(null);
105: } catch (Exception ex) {
106: throw new RuntimeException(ex);
107: }
108: }
109: ...
110: }
111:
112: }
113:
I believe this may improved, so that it could use singleton beans instead of static methods. Also more work has to be done to pass the phase event as a parameter.
An easier way to implement this with non-static methods would be using the CDIs event producer/observer api.
Producer/Observer
Here is my client bean looks like :
1: @ApplicationScoped
2: @Named
3: public class TestBean implements Serializable {
4:
5: public void afterRestoreView(@Observes
6: @PhaseEventDefinition(value=CycleId.RESTORE_VIEW, when=AfterBeforeEnum.AFTER)
7: PhaseEventHolder holder) {
8: System.out.println("after restore view : " + holder.getEvent().getPhaseId());
9: }
10:
11: }
@Observers annotation states that this bean will observe events and the @PhaseEventDefinition tells which phase we will listen to. PhaseEventHolder object holds the PhaseEvent parameters that's missing on the previous example. Again we will need a phase listener that would listen to all phases and forward them as events, wrapping a jsf PhaseEvent with our PhaseEventHolder.
1: public class ProxyPhaseListener
2: implements PhaseListener {
3:
4: private PhaseProducer phaseProducer;
5:
6: public void afterPhase(PhaseEvent event) {
7: fireEvent(event,AfterBeforeEnum.AFTER);
8: }
9:
10:
11: public void beforePhase(PhaseEvent event) {
12: fireEvent(event,AfterBeforeEnum.BEFORE);
13: }
14:
15: private void fireEvent(PhaseEvent event, AfterBeforeEnum when) {
16: final int ordinal = event.getPhaseId().getOrdinal();
17: final CycleId[] cycles = CycleId.values();
18: PhaseEventHolder phaseEventHolder = new PhaseEventHolder(event);
19: AnnotationLiteral<PhaseEventDefinition> annotationLiteral =
20: new PhaseLiteral(cycles[ordinal], when);
21: getPhaseProducer().fireEvent(phaseEventHolder,annotationLiteral);
22: }
23:
24: private PhaseProducer getPhaseProducer() {
25: if(phaseProducer == null) {
26: FacesContext context = FacesContext.getCurrentInstance();
27: phaseProducer = (PhaseProducer) context.getApplication()
28: .getELResolver().getValue(context.getELContext(),null,"phaseProducer");
29: }
30: return phaseProducer;
31: }
32:
33: public PhaseId getPhaseId() {
34: return PhaseId.ANY_PHASE;
35: }
36: }
37:
PhaseProducer is the bean that fires the phase holders as events:
1: @ApplicationScoped
2: @Named
3: public class PhaseProducer implements Serializable {
4:
5: @Inject @Any
6: private Event<PhaseEventHolder> phaseEvent;
7:
8:
9: public void fireEvent(PhaseEventHolder phaseEventHolder, AnnotationLiteral<PhaseEventDefinition> annotationLiteral) {
10: phaseEvent.select(annotationLiteral).fire(phaseEventHolder);
11: }
12: }
This approach is much simpler, usefull and clearer than the first one. Only thing I am not happy with it is that I had use EL to access the phaseProducer object.
I keep the source here so, chek it out. It should run in a glassfish-v3 environment.
Wednesday, December 16, 2009
Developing Custom Scopes/Contexts For Weld
This one came up while developing an example JEE6 project, which I'll add it up here in the future. The case is I had a textbox bound to a request scoped bean. When user triggers the paint action the value in the textbox is to be added to the list below and the textbox should be empty. I thought marking the component request scoped should have been enough to empty its values but it didn't.
Apparently to empty the value;
1. I might set the value of the field at the action method. Use a clone for the list.
2. Use a JSF component that doesn't redisplay value after post back like the inputSecret.
3. Develop a custom scope that recreates it self after actions are invoked.
Anyway maybe I am missed a simpler solution but I chose number 3 :) .
To do that first thing is to create a new scope type. I called my scope the "ActionScoped":
1: @NormalScope(passivating=false)
2: @Retention(RUNTIME)
3: @Target({TYPE, METHOD})
4: @Inherited
5: public @interface ActionScoped {
6: }
@NormalScope annotations marks an annotation as a scope-type. Next we need a context that would define when these action scoped objects exist like the request scope exist while there is a http request... This is the action context :
1: import org.jboss.weld.context.AbstractThreadLocalMapContext;
2: import org.jboss.weld.context.api.helpers.ConcurrentHashMapBeanStore;
3:
4: public class ActionContext extends AbstractThreadLocalMapContext {
5:
6: private static ActionContext instance = new ActionContext();
7:
8: private ActionContext() {
9: super(ActionScoped.class);
10: }
11:
12: public static ActionContext getInstance() {
13: return instance;
14: }
15:
16: @Override
17: protected boolean isCreationLockRequired() {
18: return false;
19: }
20:
21: public void activate() {
22: setActive(true);
23: setBeanStore(new ConcurrentHashMapBeanStore());
24: }
25:
26: public void deActivate() {
27: destroy();
28: setActive(false);
29: setBeanStore(null);
30: }
31:
32: public void reActivate() {
33: deActivate();
34: activate();
35: }
36: }
It's backed with an thread local object which is handled by the weld parent class. Bean store is where we are going to store the scoped beans. Plus I added some methods to activate (set a new bean store) /deactivate (destroy the bean store) the context. Now this context has to be activated with the start of the restore view.Deactivated and reactivated after the invoke application phase. Here is a phase listener that does that :
1: public class ActionScopedPhaseListener implements PhaseListener {
2:
3: public void beforePhase(PhaseEvent event) {
4: if (event.getPhaseId().equals(PhaseId.RESTORE_VIEW)) {
5: ActionContext.getInstance().activate();
6: }
7: }
8:
9: public void afterPhase(PhaseEvent event) {
10: if (event.getPhaseId().equals(PhaseId.RENDER_RESPONSE)) {
11: ActionContext.getInstance().deActivate();
12: } else if (event.getPhaseId().equals(PhaseId.INVOKE_APPLICATION)) {
13: ActionContext.getInstance().reActivate();
14: }
15: }
16:
17:
18: public PhaseId getPhaseId() {
19: return PhaseId.ANY_PHASE;
20: }
21: }
22:
Now last thing we have to do is register our context object. In order to do that we need to define an 'extension'. There is a nice example here about extensions, spi... Without an extension we are not able listen to events fired from the weld container which we could use to add our new context object. To define an new context we need the META-INF/services/javax.enterprise.inject.spi.Extension file which contains the qualified name of our extensions class. In this case it's 'org.mca.ewall.extensions.Extensions'. Here is what the class looks like :
1: public class Extensions implements Extension, Service{
2:
3: public void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager manager) {
4: event.addContext(ActionContext.getInstance());
5: }
6:
7: public void cleanup() {
8: }
9: }
It simply registers the context object after the application starts up (after the beans are discovered by the weld container). Now the beans could be annotated as @ActionScoped.
Wednesday, December 9, 2009
State of the 'Dependecy Injection'
"Dependecy Injection" is one of the most popular design patterns on the Java platform. It was suggested by Martin Fowler, here, instead of the term "Inversion of control". Article was published on 2004. What it brings to a application is a way to create, compose, use and destroy any java object, which are called beans.
The leading framework that first used this approach was the "the Spring Framework". The approach emerged as a alternative to EJB's. The applications built with it are easier to test and offered a easy way to integrate to most of the other frameworks and technologies out there. If you check out the api packages you can see the support for other frameworks like jsf, hibernate etc.
Today "Dependecy Injection" is part of JEE6 named CDI, JSR-299. Reference implementation is called Weld. Here are some of the highlights of CDI:
XML vs. Annotations
CDI dumps the xml approach. However there are still some use for xml's. Every bean archive must have a META-INF/beans.xml even if its empty. This file marks the jar archive as a bean archive and is scanned for beans. 'beans.xml' is also where you enable and define the ordering of 'alternative' beans and interceptors.
Qualifiers
First thing that CDI takes to account while trying to inject a bean is the type of the bean. If however there are more than one bean that could qualify CDI requires a Qualifier meta-data to resolve the ambiguity. CDI has a way to define this meta-data as an annotation, thus making our app. strong typed apposed to the usual string based qualifier approach.
Events
By defining a few annotations we could implement the Observer pattern without any boilerplate code.
Decorators
Again with annotations we could implement the decorator pattern.
Part of JEE6
Now we could inject our beans to servlets and filters like we do to any other class.
Overall as far as I could tell CDI looks like it could improve an applications code quality making it decoupled and strong-typed. JEE6 still needs some time though, best implementation out there seems to be JBoss 6 Milestone 1.
Subscribe to:
Posts (Atom)