2016-05-24 3 views
2

Ich bin dabei, eine einfache Webanwendung zu erstellen, die auf der MVC-Architektur basiert. Ich habe eine kleine JSP-Seite mit einem HTML-Formular. Die Formulardaten werden an ein Servlet weitergeleitet, das dann an die Controller-Klasse delegiert wird.Java EE-Fehler: javax.enterprise.inject.UnsatisfiedResolutionException: Api-Typ

Wenn ich auf das Formular klicke, bekomme ich einen HTTP Status 500 - Fehler verursacht durch eine "UnzufriedeneResolutionException". Es scheint, dass der Container den Controller nicht finden kann?

Eine Context.xml Datei dient als meine Datenquelle. Ich benutze Apache Tomee Webprofil 1.7.4.

den Fehler:

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) 

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); 
     } 
    } 
} 

CustomerController.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); 
     } 
    } 
} 

Web.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> 

persistence.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> 

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> 

build.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> 

Build.properties:

server.dir=C:/myprograms/apache-tomee-webprofile-1.7.4/webapps 
classpath=target/ide/classes 
targetdeploy.dir=target/deploy/ 
appname=h6 

Ordnerstruktur:

enter image description here

+0

Ausgezeichnete Arbeit zur Verfügung gestellt 100% der benötigten Informationen in Ihrer Frage. Ich habe keine Ahnung, warum Sie abgelehnt wurden, aber Ihre Art, Fragen zu stellen, ist unglaublich. –

+0

@exabrial Ich war besorgt, dass ich zu viele Informationen enthalten hätte. Vielleicht war das der Grund für den Downvote. – Irfaan

Antwort

0

würde ich nicht empfehlen basierend auf Strings Injektion, wie Sie in diesem Beispiel haben; Ihr Code funktioniert tatsächlich gut für mich, so etwas anderes in Ihrem Projekt ist falsch verursacht das Problem, das Sie nicht veröffentlicht haben. Sie können diese Probleme vermeiden, indem Sie kompilierte Qualifier anstelle von String-basierten verwenden.

Anstatt also diese:

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

....

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

einfach dies zu tun: (wenn Sie nur eine Implementierung von Controller haben)

@Inject 
private Controller customerController; 

.. ..

@ApplicationScoped 
public class CustomerController implements Controller { 

Und du bist fertig. Sie haben den Code nicht an Controller gesendet, oder wenn es mehrere Implementierungen von Controller gab. Angenommen, Sie haben mehrere Implementierungen, gibt es eine Menge Möglichkeiten, wie Sie damit umgehen können, je nach Ihren Anforderungen.

Easiest:

@Inject 
private CustomerController customerController; 

flexibler:

@Qualifier 
@Retention(RUNTIME) 
@Target({FIELD, TYPE}) 
public @interface Customer { 
} 

...

@Inject 
@Customer 
private Controller customerController; 

...

@ApplicationScoped 
@Customer 
public class CustomerController implements Controller { 

Oder vielleicht haben Sie nur mehrere Implementierungen, aber Sie müssen die Implementierung in eine Weile Anwendung jeder einmal breit ändern:

@Inject 
private Controller customerController; 

...

@ApplicationScoped 
@Default 
public class CustomerController implements Controller { 

...

@ApplicationScoped 
@Alternative 
public class AnotherCustomerController implements Controller { 

... um die Alternative zu aktivieren:

<beans ... > 
    <alternatives> 
     <class>a1.AnotherCustomerController</class> 
    </alternatives> 
</beans> 

Viel Glück! Post antwortet zurück mit weiteren Fragen oder Follow-up!

PS:

benutzte ich @ApplicationScoped statt @Dependent weil der Code keinen gemeinsamen Staat zu haben scheint.

+0

Danke für die Tipps. Die Einstellung 'metadata-complete' auf' false' in web.xml scheint das Problem gelöst zu haben. Ich beabsichtige jedoch, weitere Implementierungen von 'Controller' hinzuzufügen und dann die Formulardaten unter Verwendung einer Eigenschaftendatei dem entsprechenden Controller zuzuordnen. Die Anmerkungen, die Sie erwähnten, könnten noch nützlich sein. – Irfaan

+0

Froh, dass du es herausgefunden hast! –