Java EE 错误:javax.enterprise.inject.UnsatisfiedResolutionException:Api 类型

Irf*_*aan 5 model-view-controller jsp ejb apache-tomee jakarta-ee

我正在构建一个基于 MVC 架构的简单 Web 应用程序。我有一个带有 HTML 表单的小型 JSP 页面。表单数据被转发到 servlet,然后委托给 Controller 类。

单击表单上的提交时,我收到 HTTP Status 500 - 由“UnsatisfiedResolutionException”引起的错误。容器好像找不到Controller?

文件Context.xml作为我的数据源。我正在使用 apache tomee webprofile 1.7.4。

错误:

type Exception report

message Error instantiating servlet class a1.DispatcherServlet

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Error instantiating servlet class a1.DispatcherServlet
    org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)
root cause

javax.enterprise.inject.UnsatisfiedResolutionException: Api type [a1.Controller] is not found with the qualifiers 
Qualifiers: [@javax.inject.Named(value=customerController)]
for injection into Field Injection Point, field name :  customerController, Bean Owner : [DispatcherServlet, Name:null, WebBeans Type:DEPENDENT, API Types:[java.io.Serializable,javax.servlet.GenericServlet,java.lang.Object,a1.DispatcherServlet,javax.servlet.Servlet,javax.servlet.http.HttpServlet,javax.servlet.ServletConfig], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]]
    org.apache.webbeans.util.InjectionExceptionUtil.throwUnsatisfiedResolutionException(InjectionExceptionUtil.java:60)
    org.apache.webbeans.container.InjectionResolver.getInjectionPointBean(InjectionResolver.java:250)
    org.apache.webbeans.inject.AbstractInjectable.inject(AbstractInjectable.java:76)
    org.apache.webbeans.inject.InjectableField.doInjection(InjectableField.java:65)
    org.apache.webbeans.portable.InjectionTargetImpl.injectFields(InjectionTargetImpl.java:208)
    org.apache.webbeans.portable.InjectionTargetImpl.inject(InjectionTargetImpl.java:194)
    org.apache.webbeans.portable.InjectionTargetImpl.inject(InjectionTargetImpl.java:184)
    org.apache.webbeans.component.AbstractOwbBean.create(AbstractOwbBean.java:125)
    org.apache.openejb.core.WebContext.newInstance(WebContext.java:138)
    org.apache.tomee.catalina.JavaeeInstanceManager.newInstance(JavaeeInstanceManager.java:46)
    org.apache.tomee.catalina.JavaeeInstanceManager.newInstance(JavaeeInstanceManager.java:66)
    org.apache.tomee.catalina.JavaeeInstanceManager.newInstance(JavaeeInstanceManager.java:61)
    org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)
Run Code Online (Sandbox Code Playgroud)

DispatcherServlet.java:

package a1;

/* Imports */

public class DispatcherServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Inject
    @Named("customerController")
    private Controller customerController;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            String methodName = "addCustomer";

            Method method = customerController.getClass().getDeclaredMethod(methodName, HttpServletRequest.class);
            method.setAccessible(true);
            method.invoke(customerController, req);

            req.getRequestDispatcher("/success.jsp").forward(req, resp);
        } catch (SecurityException | IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

客户控制器.java:

package a1;

/* Imports */

@Named("customerController")
public class CustomerController implements Controller {

    @EJB
    private CustomerService customerServiceImpl;

    private void addCustomer(HttpServletRequest req) {
        long cn1 = Long.parseLong(req.getParameter("form_cust_no"));
        String n = req.getParameter("form_name");
        String s = req.getParameter("form_surname");

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            String formDate = req.getParameter("form_dob");
            java.util.Date dateUtil = sdf.parse(formDate);
            java.sql.Date dateSql = new java.sql.Date(dateUtil.getTime());
            Customer customer = new Customer(cn1, n, s, dateSql);

            customerServiceImpl.addCustomer(customer);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

网页.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0" metadata-complete="true">

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>a1.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/dispatcher/*</url-pattern>
    </servlet-mapping>

    <resource-ref>
        <res-ref-name>jdbc/MyDataSource</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</web-app>
Run Code Online (Sandbox Code Playgroud)

持久性.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="Ejb1" transaction-type="JTA">
        <jta-data-source>jdbc/MyDataSource</jta-data-source>

        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <property name="hibernate.connection.autocommit" value="false" />
        </properties>
    </persistence-unit>
</persistence>
Run Code Online (Sandbox Code Playgroud)

Beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
Run Code Online (Sandbox Code Playgroud)

构建.xml

<?xml version="1.0"?>
<project name="h6" default="all" basedir=".">
    <description>Homework 6</description>

    <property file="build.properties" />

    <path id="master-classpath">
        <fileset dir="C:/myprograms/apache-tomee-webprofile-1.7.4/lib" />
        <pathelement path="/a1/" />
    </path>

    <target name="clean" description="Clean class files and war files">
        <delete file="${targetdeploy.dir}${appname}.war" failonerror="false" />
        <delete file="${server.dir}/${appname}.war" failonerror="false" />
        <delete dir="${server.dir}/${appname}" failonerror="false" />
        <delete dir="/${classpath}/" failonerror="false" />
    </target>

    <target name="compile" depends="clean" description="Compile all files into target">
        <javac srcdir="./src/main/java" destdir="./${classpath}" includeAntRuntime="false">
            <classpath refid="master-classpath" />
        </javac>
    </target>

    <target name="copy-classes" depends="compile" description="Copy classes from target into webapp">
        <copy todir="src/main/webapp/WEB-INF/classes/">
            <fileset dir="${classpath}" includes="**/*.class" />
            <fileset dir="${classpath}" includes="**/*.xml" />
        </copy>
        <copy todir="src/main/webapp/WEB-INF/lib/">
            <fileset dir="${classpath}" includes="**/*.jar" />
        </copy>
    </target>

    <target name="generate-war" depends="copy-classes" description="Generate war file from webapp contents">
        <war destfile="./${targetdeploy.dir}${appname}.war" webxml="src/main/webapp/WEB-INF/web.xml">
            <fileset dir="src/main/webapp/">
                <include name="**/*.class" />
                <include name="**/*.jsp" />
                <include name="**/*.css" />
                <include name="**/*.html" />
                <include name="**/*.txt" />
                <include name="**/*.properties" />
                <include name="**/*.jar" />
                <include name="**/*.xml" />
            </fileset>
        </war>
    </target>

    <target name="deploy-war" depends="generate-war" description="Copy war file into server">
        <copy todir="${server.dir}/">
            <fileset dir="${targetdeploy.dir}">
                <include name="*.war" />
            </fileset>
        </copy>
    </target>

    <target name="extract-war" depends="deploy-war">
        <mkdir dir="${server.dir}/${appname}" />
        <unwar src="${server.dir}/${appname}.war" dest="${server.dir}/${appname}" />
    </target>

    <target name="all" depends="extract-war" />
</project>
Run Code Online (Sandbox Code Playgroud)

构建属性:

server.dir=C:/myprograms/apache-tomee-webprofile-1.7.4/webapps
classpath=target/ide/classes
targetdeploy.dir=target/deploy/
appname=h6
Run Code Online (Sandbox Code Playgroud)

文件夹结构:

在此输入图像描述

Jon*_*her 3

建议像本示例中那样基于字符串进行注入;您的代码实际上对我来说工作得很好,所以您的项目中的其他错误导致了您没有发布的问题。您可以通过使用编译的限定符而不是基于字符串的限定符来避免这些问题。

所以代替这个:

@Named("customerController")
public class CustomerController implements Controller {
Run Code Online (Sandbox Code Playgroud)

....

@Inject
@Named("customerController")
private Controller customerController;
Run Code Online (Sandbox Code Playgroud)

只需这样做:(如果您只有一种实现Controller

@Inject
private Controller customerController;
Run Code Online (Sandbox Code Playgroud)

....

@ApplicationScoped
public class CustomerController implements Controller {
Run Code Online (Sandbox Code Playgroud)

你就完成了。您没有将代码发布到Controller,或者是否有多个实现Controller。假设您确实有多个实现,那么根据您的要求,您可以通过多种方式来处理它。

最简单:

@Inject
private CustomerController customerController;
Run Code Online (Sandbox Code Playgroud)

更灵活:

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE})
public @interface Customer {
}
Run Code Online (Sandbox Code Playgroud)

...

@Inject
@Customer
private Controller customerController;
Run Code Online (Sandbox Code Playgroud)

...

@ApplicationScoped
@Customer
public class CustomerController implements Controller {
Run Code Online (Sandbox Code Playgroud)

或者也许您只有多个实现,但您需要每隔一段时间在应用程序范围内更改实现:

@Inject
private Controller customerController;
Run Code Online (Sandbox Code Playgroud)

...

@ApplicationScoped
@Default
public class CustomerController implements Controller {
Run Code Online (Sandbox Code Playgroud)

...

@ApplicationScoped
@Alternative
public class AnotherCustomerController implements Controller {
Run Code Online (Sandbox Code Playgroud)

...

然后激活替代方案:

<beans ... >
    <alternatives>
        <class>a1.AnotherCustomerController</class>
    </alternatives>
</beans>
Run Code Online (Sandbox Code Playgroud)

祝你好运!回复更多问题或跟进!

附:

我使用@ApplicationScoped而不是@Dependent因为您的代码似乎没有共享状态。