Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Container Managed DataSource Object in Structs Action

I am new to use Struts 2 Framework.

I need to use DataSource Object in Struts Action Class. My platform is Tomcat 8 (Servlet 3.1) and I set Resource in context.xml.

I can inject Container managed DataSource Object in a servlet by using @Resource annotation.

I'd tried in this way. I create a ServletContextListener and inject DataSource in this listener. I set this datasource to application scope object in contextInitialized method.

@WebListener
public class ResourceListener implements ServletContextListener {

    @Resource(name="jdbc/skill_db")
    private DataSource ds;

    public ResourceListener() { }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Start");
        sce.getServletContext().setAttribute("Datasource", ds);
        sce.getServletContext().setAttribute("dbConfigStream", sce.getServletContext().getResourceAsStream("/WEB-INF/database.properties"));
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) { }

}

After that I access application scope and get this datasource from Struts Action methods.

public String welcome() {

    Map<String, Object> application = ActionContext.getContext().getApplication();
    DataSource ds = (DataSource) application.get("Datasource");
    InputStream conf = (InputStream) application.get("dbConfigStream");

    Model<Employee> empModel = new BaseModel<Employee>(Employee.class, 
        Employee::convert, ds, conf);
    list = empModel.getAll();

    return "welcome";
}

My question are :

  1. Can I get DataSource object in a structs action object?
  2. Is this way that I tried a correct way in struts?
like image 425
Min Lwin Avatar asked Oct 19 '22 03:10

Min Lwin


1 Answers

I tried my requirements by Struts2-CDI Plugin By using CDI I can inject my dependencies.

1. I edit POM of my project as follow.

    <dependency>
        <groupId>org.apache.struts</groupId>
        <artifactId>struts2-cdi-plugin</artifactId>
        <version>2.3.24</version>
    </dependency>
    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <version>1.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.weld.servlet</groupId>
        <artifactId>weld-servlet</artifactId>
        <version>2.2.15.Final</version>
    </dependency> 

2. As I used Tomcat I need to add this codes to context.xml and web.xml to use CDI.

2.1 context.xml

<Resource name="BeanManager" auth="Container"
    type="javax.enterprise.inject.spi.BeanManager" 
    factory="org.jboss.weld.resources.ManagerObjectFactory" />

2.2 web.xml

  <resource-env-ref>
    <resource-env-ref-name>BeanManager</resource-env-ref-name>
    <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
  </resource-env-ref>

3. Produce Datasource

Inject directly DataSource object and ServletContext into ResourceProducer class. So that I don't need listener class to set DataSource to application scope and also don't need to access indirectly to servlet context object.

Using CDI make free the limitations of Struts.

@ApplicationScoped
public class ResourceProducer {

    @Resource(name="jdbc/skill_db")
    private DataSource datasource;

    @Inject
    private ServletContext servletContext;


    @Produces
    @DbResourse
    public DataSource getDatasource() {
        return datasource;
    }

    @Produces
    @DbConfiguration
    public InputStream getConfiguration() {
        return servletContext.getResourceAsStream("/WEB-INF/database.properties");
    }

}

4. Inject DataSource at Model Producer

@Inject
@DbResourse
private DataSource ds;
@Inject
@DbConfiguration
private InputStream dbConfig;

@Produces
@DataModel(Employee.class)
public Model<Employee> getEmployeeModel() {
    return new BaseModel<Employee>(Employee.class, Employee::convert, ds, dbConfig);
}

5. Inject Model at Struts 2 Action Class

@Inject
@DataModel(Employee.class)
private Model<Employee> empModel;

public String welcome() {

    list = empModel.getAll();

    return "welcome";
}
like image 158
Min Lwin Avatar answered Nov 01 '22 10:11

Min Lwin