[Logo] Mentawai Forum - Mentawai Web Framework
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 

Forum Read-Only! Check the new site and forum here!

Using Mentawai along with Guice  XML
Forum Index -> General Comments Go to Page: 1, 2 Next 
Author Message
Sven



Joined: 20/01/2008 05:53:15
Messages: 24
Offline

Hi Mentawai'ans

I've adopted Google Guice recently. I'm using Guice instead of the Mentawai Dependency Injection functionality since my project consists of several subprojects, only one of them being a web application. Also I think that Guice is more powerful for DI (no offense!) and I like configuration by annotations.

Anyway, I ask myself why the ActionConfig constructor can only take classes and no instances of objects. Latter would improve the integration of Guice in Mentawai:

Let's say there's a SearchAction class. Since the search is performed on a database, an instance of SearchAction holds an instance of Database (the service)

Code:
class SearchAction extends BaseAction {
   private Database database;
 
   @Inject
   public SearchAction( Database database ) {
     this.database = database;
   }
 
   // other methods
 }

Assuming Guice has been properly configured and an Injector instance has been created, the action could be configured like this:

Code:
ActionConfig = new ActionConfig( "/search", injector.getInstance( SearchAction.class ) );

Is there any good reason why the ActionConfig constructor only takes classes? If it would also take instances it could hold these instances until the corresponding action is called.

Even if no DI framework is used this could improve Mentawai because custom constructors of the actions could be called.
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline


The only reason why Mentawai takes classes and NOT instances is because a new instance is created for each new request. This will make the actions thread-safe.

If we make the ActionConfig take an instance, then you must make sure your instance is thread-safe. I have no objection of providing an ActionConfig that takes an instance, but we should not encourage its usage, unless it is really a necessity and the guy knows what he is doing.

Now talking about DI, I also like Guice. I understand that you want to use Guice, but allow me to illustrate how your case can be easily solved with Mentawai DI:

Code:
 filter(new IoCFilter());
 filter(new InjectionFilter());
 
 ioc("database", MyDatabaseImpl.class, APPLICATION); // you can also use REQUEST and SESSION
 


And your action:

Code:
 class SearchAction extends BaseAction {
    
    private Database database;
  
    // other methods
  }
 


You can use a setter, but you do not need one. Injection will happen straight in the private field by the InjectionFilter.




Sergio Oliveira

saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline


I think I found out what you were looking for, Sven. Mentawai already comes with it.

SingleInstanceActionConfig: This action config will accept an action instance and it will always return this same instance to all requests:

http://www.mentaframework.org/api/org/mentawai/core/SingleInstanceActionConfig.html

API DOC wrote:

Use this action config if you want your action to be a single instance for all requests, in other words, you don't want to create a new instance of your action for every request. If you use this action config, it is your responsibility to make your action thread-safe. If you are not sure that your action is thread-safe, than you should not use this action config. Sometimes our actions are so simple (Ex: org.mentawai.action.SuccessAction) that it doesn't make sense to create a new instance for every request.
 


SingleInstanceBaseAction: Extend this class if you want an single-instance AND single-threaded action. This will make all the action protected members (input, output, session, etc.) thread safe through ThreadLocals.

http://www.mentaframework.org/api/org/mentawai/core/SingleInstanceBaseAction.html

API DOC wrote:

This is the base class for single instance actions, in other words, those actions that will be instantiated only once and shared among all requests. Sometimes, when you looking for every performance drop, you may not want to create a new action instance for every request. This class keeps the action data in thread locals, so that each thread has its own input, output, session, application and locale. The actions extending this class must be configurated with a SingleInstanceActionConfig. It is your responsibility to make your action thread-safe, otherwise you should stick with the BaseAction class.
 


But now I am very muched pumped to make an good integration of Guice and Mentawai.

Sergio Oliveira

Sven



Joined: 20/01/2008 05:53:15
Messages: 24
Offline

Hello Sergjo,

I didn't think about thread-safety, pardon me!

I could use the SingleInstanceActionConfig but I will also think about a solution how to use Guice with the standard ActionConfig.
Sven



Joined: 20/01/2008 05:53:15
Messages: 24
Offline

By the way, I'm already using Guice functionality which goes beyond that of Mentawai. For example the Database class contains another service, the DatabaseHandler, which does the actual job.

There can be different database handlers, a JDODatabaseHandler and a MockDatabaseHandler (for testing).

Which handler actually is inserted is configured in a Module class.
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline


I could use the SingleInstanceActionConfig but I will also think about a solution how to use Guice with the standard ActionConfig.
 


We should think about a filter or something else to provide a very good integration between Mentawai and Guice. Maybe like the Spring integration? Let me know if you come up with something. I will take a look on how Guice works and give it a thought as well.


By the way, I'm already using Guice functionality which goes beyond that of Mentawai. For example the Database class contains another service, the DatabaseHandler, which does the actual job.

There can be different database handlers, a JDODatabaseHandler and a MockDatabaseHandler (for testing).

Which handler actually is inserted is configured in a Module class.
 


I think you will be fine using Guice, but just as a reference, you can do that very easily with the Mentawai support for auto-wiring.

So you want to insert a DatabaseHandler inside your Database, and the DatabaseHander will have many implementations, right? All you have to do is this:

Code:
 filter(new IoCFilter());
 filter(new DIFilter());
 filter(new InjectionFilter());
 
 ioc("database", MyDatabaseImpl.class);
 ioc("databaseHandler", JDODatabaseHandler.class);
 
 // auto-wiring
 di("databaseHandler", DatabaseHandler.class);
 


Take a look in the recipe for more details: http://recipes.mentaframework.org/posts/list/14.page


Sergio Oliveira

saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline


Checking here: http://www.mentaframework.org/spring.jsp?loc=en

I think we should create a GuiceActionConfig and a GuiceFilter, pretty much like SpringActionConfig and SpringFilter.

Feel free to help here Sven, but only if you have the time and the desire to play with it.

Thanks dude!

Sergio Oliveira

Sven



Joined: 20/01/2008 05:53:15
Messages: 24
Offline

saoj wrote:

I think we should create a GuiceActionConfig and a GuiceFilter, pretty much like SpringActionConfig and SpringFilter.

Feel free to help here Sven, but only if you have the time and the desire to play with it.  

Funny, I also thought that we need a GuiceActionConfig. It should have a constructor like this:

Code:
GuiceActionConfig( String, com.google.inject.Injector, Class )


I will see if I have the time to implement it. I still don't know how to implement a GuiceFilter yet, though.
Sven



Joined: 20/01/2008 05:53:15
Messages: 24
Offline

Ok, here it is!

It works in my project but it still needs extensive testing!

Code:
package org.mentawai.core;
 
 import org.mentawai.core.Action;
 import org.mentawai.core.ActionConfig;
 import org.mentawai.core.PojoAction;
 
 import com.google.inject.Injector;
 
 /**
  * ActionConfig to tightly integrate Google Guice.
  * 
  * Use this ActionConfig if you want Guice to create your
  * Action instances and resolve all dependencies.
  * 
  * @author Sven Jacobs <sven.jacobs@web.de>
  * @version 0.1
  */
 public class GuiceActionConfig extends ActionConfig {
   private Injector injector;
   
   public GuiceActionConfig( Injector injector, Class<? extends Object> klass ) {
     super( klass );
     this.injector = injector;
   }
   
   public GuiceActionConfig( String name, Injector injector, Class<? extends Object> klass )
   {
     super( name, klass );
     this.injector = injector;
   }
   
   @Override
   public Action getAction() {
     Object instance = injector.getInstance( actionClass );
     
     if ( Action.class.isAssignableFrom( actionClass ) ) {
       return (Action)instance;
     } else {
       return new PojoAction( instance );
     }
   }
 }

EDIT: The org.mentawai.core.* imports are unnecessary. I needed them because I placed GuiceActionConfig in a different package. Feel free to remove them

 Filename GuiceActionConfig.java [Disk] Download
 Description GuiceActionConfig
 Filesize 1 Kbytes
 Downloaded:  300 time(s)

saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline


I haved added this filter to org.mentawai.guice

I changed the order of the constructor parameters and added another constructor.

Take a look:

Code:
 package org.mentawai.guice;
  
  import org.mentawai.core.Action;
 import org.mentawai.core.ActionConfig;
 import org.mentawai.core.PojoAction;
 
 import com.google.inject.Injector;
  
  /**
   * ActionConfig to tightly integrate Google Guice.
   * 
   * Use this ActionConfig if you want Guice to create your
   * Action instances and resolve all dependencies.
   * 
   * @author Sven Jacobs <sven.jacobs@web.de>
   * @version 0.1
   */
  public class GuiceActionConfig extends ActionConfig {
 	 
    private Injector injector;
    
    public GuiceActionConfig( Class<? extends Object> klass, Injector injector ) {
      super( klass );
      this.injector = injector;
    }
    
    public GuiceActionConfig( String name, Class<? extends Object> klass, Injector injector ) {
      super( name, klass );
      this.injector = injector;
    }
    
    public GuiceActionConfig( String name, Class<? extends Object> klass, String innerAction, Injector injector ) {
 	   super( name, klass, innerAction);
 	   this.injector = injector;
    }
    
    @Override
    public Action getAction() {
 	   
      Object instance = injector.getInstance( actionClass );
      
      if ( Action.class.isAssignableFrom( actionClass ) ) {
     	 
        return (Action) instance;
        
      } else {
     	 
        return new PojoAction( instance );
        
      }
    }
  }
 


Sergio Oliveira

Sven



Joined: 20/01/2008 05:53:15
Messages: 24
Offline

Nice!

Is it in the beta jar?
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline


Yes.

We are only missing now a GuiceInput, similar to SpringInput.

That's to request an object from the input and get it from Guice container. A GuiceFilter would setup the GuiceInput as the action input.

Sergio Oliveira

velo


[Avatar]

Joined: 16/02/2006 13:33:54
Messages: 1197
Location: Jaraguá do Sul - SC
Offline

Guys, you are both insane!

ROFL =P


Sven, I like a lot your idea. Never say something earlier because some days I'm lazy =D


VELO

_____________________________________
Mentawai Developer
"When the only tool you have is a hammer, everything looks like a nail"
http://en.wikipedia.org/wiki/Golden_hammer
[Email] [MSN]
Sven



Joined: 20/01/2008 05:53:15
Messages: 24
Offline

@velo: Thank you!

saoj wrote:

Yes.

We are only missing now a GuiceInput, similar to SpringInput.

That's to request an object from the input and get it from Guice container. A GuiceFilter would setup the GuiceInput as the action input. 

I'm still thinking how to do it the "Guice" way... The problem is, with the name from the action input alone Guice doesn't know what kind of class to instantiate. So I believe we have to add another layer of configuration, something like this:

Code:
 GuiceFilter gf = new GuiceFilter()
 gf.bind( "myinput", MyClass.class );
 
 addGlobalFilter( gf );

The GuiceFilter then needs to pass this configuration to the GuiceInput... I don't quite like it but I don't see another way. Do you have a better idea?
velo


[Avatar]

Joined: 16/02/2006 13:33:54
Messages: 1197
Location: Jaraguá do Sul - SC
Offline

Why don't reuse current ioc method on appManager?
http://www.mentaframework.org/ioc.jsp

Code:
 ...
     public void init() {
         
         // Define the IoC components...
         
         ioc("talker1", PortugueseTalker.class);
         
         ioc("talker2", PoliteTalker.class)
             .addProperty("name", "Polite guy");
             
         ioc("talker3", UnpoliteTalker.class, SESSION)
             .addInitValue("Unpolite guy");
             
     }
 

_____________________________________
Mentawai Developer
"When the only tool you have is a hammer, everything looks like a nail"
http://en.wikipedia.org/wiki/Golden_hammer
[Email] [MSN]
 
Forum Index -> General Comments Go to Page: 1, 2 Next 
Go to:   
Powered by JForum 2.1.6 © JForum Team