无法使用ApacheTomcat 8注入数据源

时间:2016-11-14 06:36:46

标签: java jdbc jsf-2 tomcat8

这是我第一次尝试使用DataSource,而且是JSF的新功能,以及它与JDBC的集成。

我在context.xml中定义了资源(在META-INF文件夹中),并在web.xml中添加了资源引用<resource-ref>(包含在WEB-INF文件夹中)。然后我创建了ManagedBean。

这是我在Netbeans中创建的数据库的屏幕截图。

enter image description here

AddressBean.java

package com.addressbook.pkg;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.faces.bean.ManagedBean;
import javax.sql.DataSource;
import javax.sql.rowset.CachedRowSet;

@ManagedBean(name="addressBean")
public class AddressBean {
    private String firstName;
    private String lastName;
    private String street;
    private String city;
    private String state;
    private String zipcode;

    //allow server to inject the DataSource
    @Resource(name="jdbc/addressbook")
    DataSource dataSource;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getZipcode() {
        return zipcode;
    }

    public void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }

    public ResultSet getAddresses()throws SQLException{

        //check whether dataSource was injected by the server
        if(dataSource == null){
            throw new SQLException("Unable to obtain DataSource");
        }

        //obtain a connection from the connection pool
        Connection connection = dataSource.getConnection();

        //check whether the connection was successful
        if(connection == null){
            throw new SQLException("Unable to connect to DataSource");
        }

        try{
            //create a PreparedStatement to insert a new address book entry
            String SQL = "SELECT firstname, lastname,street, city, state,zip FROM addresses ORDER BY LASTNAME, FIRSTNAME";
            PreparedStatement getAddresses = connection.prepareStatement(SQL);

            CachedRowSet rowSet = new com.sun.rowset.CachedRowSetImpl();
            rowSet.populate(getAddresses.executeQuery());
            return rowSet;
        }finally{
            connection.close();
        }
    }//end of getAddresses()


    public String save()throws SQLException{
        //check whether the datasource was injected by the server
        if(dataSource == null){
            throw new SQLException("Unable to obtain DataSource");
        }
        //obtain connection from the connection pool
        Connection connection = dataSource.getConnection();

        //check whether connection  was successful
        if(connection == null){
            throw new SQLException("Unable to connect to DataSource");
        }
        try{
            String SQL = "INSERT INTO addresses(firstname,lastname,street,city,zip)VALUES(?,?,?,?,?,?)";
            PreparedStatement addEntry = connection.prepareStatement(SQL);

            //specify the PreparedStatement's arguments
            addEntry.setString(1,getFirstName());
            addEntry.setString(2, getLastName());
            addEntry.setString(3,getStreet());
            addEntry.setString(4,getCity());
            addEntry.setString(5, getState());
            addEntry.setString(6,getZipcode());

            addEntry.executeUpdate(); //insert the entry
            return "index"; //go back to index.xhtml page
        }
        finally{
            connection.close();
        }
    }

}

context.xml中

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/addressbook">
    <Resource name="jdbc/addressbook" auth="Container" type="javax.sql.DataSource"
               maxActive="50" maxIdle="30" maxWait="10000"
               username="root" password=""
               driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/testdb"/>

</Context>

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 
         xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                                http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>

    <resource-ref>
    <description>MySQL Datasource example</description>
    <res-ref-name>jdbc/addressbook</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>

</web-app>

我在context.xmlweb.xml上都设置了正确的资源名称和数据库详细信息,但是当我运行项目时,我得到SQLException

java.sql.SQLException: Unable to obtain DataSource
    at com.addressbook.pkg.AddressBean.getAddresses(AddressBean.java:78)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:97)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at org.apache.el.parser.AstValue.getValue(AstValue.java:169)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:184)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
    at javax.faces.component.UIData.getValue(UIData.java:732)
    at javax.faces.component.UIData.getDataModel(UIData.java:1822)
    at javax.faces.component.UIData.setRowIndexWithoutRowStatePreserved(UIData.java:484)
    at javax.faces.component.UIData.setRowIndex(UIData.java:473)
    at com.sun.faces.renderkit.html_basic.TableRenderer.encodeBegin(TableRenderer.java:81)
    at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:864)
    at javax.faces.component.UIData.encodeBegin(UIData.java:1133)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1854)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1100)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:687)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

从我SQLException我看来它没有正确获取数据源,可能NULL

我无法弄清楚为什么它会为空。

我可以毫无问题地连接到localhost:8080。我检查了我的数据库并确认它已运行并连接到服务器。

顺便说一下,我使用 Mysql ApacheTomcat 8.0

我希望你能提供帮助。

谢谢。

1 个答案:

答案 0 :(得分:0)

我终于找到了解决问题的方法。我只是使用@Resource(name="jdbc/addressbook")类和Context方法来引用lookup()

,而不只是添加DataSource注释。
    //@Resource(name="jdbc/addressbook")
    DataSource dataSource;

public ResultSet getAddresses()throws SQLException{


        try {
            Context ctx = new InitialContext();
            dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/addressbook");
        } catch (NamingException e) {
            JOptionPane.showMessageDialog(null,"Error: "+e.getMessage());
        }

        //check whether dataSource was injected by the server
        if(dataSource == null){
            throw new SQLException("Can't get DataSource");
        }

        //obtain a connection from the connection pool
        Connection connection = dataSource.getConnection();

        //check whether the connection was successful
        if(connection == null){
            throw new SQLException("Unable to connect to DataSource");
        }

        try{
            //create a PreparedStatement to insert a new address book entry
            String SQL = "SELECT firstname, lastname,street, city, state,zip FROM addresses ORDER BY LASTNAME, FIRSTNAME";
            PreparedStatement getAddresses = connection.prepareStatement(SQL);

            CachedRowSet rowSet = new com.sun.rowset.CachedRowSetImpl();
            rowSet.populate(getAddresses.executeQuery());
            return rowSet;
        }finally{
            connection.close();
        }
    }//end of getAddresses()

只需在try-catch块中使用lookup()方法,我的网络应用就可以获得DataSource jdbc/addressbook

这可以作为替代解决方案,因为有些人在单独使用DataSource注释获取@Resource时会遇到问题。