Search code examples
ejbwebsphereejb-3.1java-ee-7

'Bean does not have a public constructor that does not take parameters' error despite clearly having one?


I have an EmailService EJB that has a very simple 'send_email' method. I'm receving the error in the title despite clearly having a public constructor that does not take parameters. Below is the exact error and the class code. This is very confusing.

Error:

[ERROR ] CNTR5007E: The websphere.jaxrs.service.EmailService bean class for the WebApiConsole#WebApiConsole.war#EmailService bean does not have a public constructor that does not take parameters.

See here for error details (not much to see): http://pic.dhe.ibm.com/infocenter/wxdinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.messages.doc%2Fcom.ibm.ejs.container.container.html

Code:

package websphere.jaxrs.service;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;

import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;

import websphere.jaxrs.helpers.ContextFinder;

    /**
     * This class provides an interface for emailing messages. It uses server environment variables to configure SMTP server and port and authentication.
     * 
     * @author me
     *
     */
    @Stateless
    @LocalBean
    public class EmailService {

        @EJB ContextFinder ctf;

        private static final String EMAIL_PASSWORD_JNDI_NAME = "EMAIL_PASSWORD";
        private static final String EMAIL_USERNAME_JNDI_NAME = "EMAIL_USERNAME";
        private static final String SMTP_SERVER_JNDI_NAME = "SMTP_SERVER";
        private static final String SMTP_PORT_JNDI_NAME = "SMTP_PORT";

        private String username;
        private String password;
        private String server;
        private Integer port;


        public EmailService() { 
            username = (String) ctf.lookup(EMAIL_USERNAME_JNDI_NAME);
            password = (String) ctf.lookup(EMAIL_PASSWORD_JNDI_NAME);
            server = (String) ctf.lookup(SMTP_SERVER_JNDI_NAME);
            port = (Integer) ctf.lookup(SMTP_PORT_JNDI_NAME);
        }

        /**
         * Sends an email to a specific user.
         * 
         * @param sendTo
         * @param subject
         * @param message
         */
        public void sendMail(String sendTo, String subject, String message) {

            try {
                Email email = new SimpleEmail();
                email.setHostName(server);
                email.setSmtpPort(port);
                email.setAuthentication(username, password);
                email.setSSLOnConnect(true);
                email.setFrom(username);
                email.setSubject(subject);
                email.setMsg(message);
                email.addTo(sendTo);
                email.send();
            } catch (EmailException e) {
                System.err.println("Failed to email");
                e.printStackTrace();
            }

        }

    }

I'm inclined to think this is a bug. I might be wrong but but everything is pretty self-contained in the class above (no other configurations that I know of required) and I keep getting this error. I tried re-building the project.

[EDIT] I did some experimentation and very specifically, removing sendMail() causes it to be error free.


Solution

  • Why you don't remove initialization from constructor into a @PostConstruct method?

    @Stateless
    public class EmailService {
        @EJB ContextFinder ctf;
    
        private static final String EMAIL_PASSWORD_JNDI_NAME = "EMAIL_PASSWORD";
        private static final String EMAIL_USERNAME_JNDI_NAME = "EMAIL_USERNAME";
        private static final String SMTP_SERVER_JNDI_NAME = "SMTP_SERVER";
        private static final String SMTP_PORT_JNDI_NAME = "SMTP_PORT";
    
        private String username;
        private String password;
        private String server;
        private Integer port;
    
        @PostConstruct
        public void init() { 
            username = (String) ctf.lookup(EMAIL_USERNAME_JNDI_NAME);
            password = (String) ctf.lookup(EMAIL_PASSWORD_JNDI_NAME);
            server = (String) ctf.lookup(SMTP_SERVER_JNDI_NAME);
            port = (Integer) ctf.lookup(SMTP_PORT_JNDI_NAME);
        }
    
        public void sendMail(String sendTo, String subject, String message) {
            // send mail
        }
    
    }