How do I define inner bean in Spring?

Inner bean is a bean defined inside another bean, it can be seen as an inner class. In another word, the inner bean is a bean defined within the scope of another bean. In this case the inner bean can only be use by the outer bean. No other bean in the Spring context can refer to that bean.

So, if you sure that a bean is only use within a single bean it is a good idea to use an inner bean. Inner bean can be injected through setter injection or constructor injection.

Here is an example of Spring configuration for an inner bean injection:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="racer" class="org.kodejava.spring.core.Racer">
        <property name="car">
            <bean class="org.kodejava.spring.core.Car">
                <property name="maker" value="Ferrari" />
                <property name="year" value="2021" />
            </bean>
        </property>
    </bean>

</beans>

In this configuration we use a setter injection. So we use the property element. Instead of using a ref attribute for referring to another bean we define the bean using the bean element inside the property element. And then we create the Car bean and sets its properties.

If you want to use a constructor injection you can inject the Car bean into the Racer bean by defining a bean inside the constructor-arg element in the Racer bean.

Below is our Racer and Car classes.

package org.kodejava.spring.core;

public class Racer {
    private Car car;

    public Racer() {
    }

    public Racer(Car car) {
        this.car = car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    @Override
    public String toString() {
        return "Racer{" +
                "car=" + car +
                '}';
    }
}
package org.kodejava.spring.core;

public class Car {
    private String maker;
    private int year;

    public void setMaker(String maker) {
        this.maker = maker;
    }

    public void setYear(int year) {
        this.year = year;
    }

    @Override
    public String toString() {
        return "Car{" +
                "maker='" + maker + "'" +
                ", year=" + year +
                '}';
    }
}

Let’s create our Demo class to run the program:

package org.kodejava.spring.core;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo {
    public static void main(String[] args) {
        var context = new ClassPathXmlApplicationContext("inner-bean.xml");

        Racer racer = (Racer) context.getBean("racer");
        System.out.println("Racer = " + racer);
        context.close();
    }
}

Here is the output of our program:

Racer = Racer{car=Car{maker='Ferrari', year=2021}}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

Maven Central Maven Central Maven Central

How do I inject into bean properties?

A bean usually have some private properties that can be accessed through a pair of accessor methods, the setters and getters. These setters, the setXXX() method can be used by Spring Framework to configure the beans.

This method of injecting beans property through their setter methods is called the setter injection. The following example will show you how to do it.

Below is our DrawingBean that have colour and shape properties. In the example we will inject both of the properties using their respective setter method. The configuration is done in the Spring application configuration file.

package org.kodejava.spring.core;

public class DrawingBean {
    private String colour;
    private Shape shape;

    public DrawingBean() {
    }

    public void drawShape() {
        getShape().draw();
        System.out.printf("The colour is %s.", getColour());
    }

    public String getColour() {
        return colour;
    }

    public void setColour(String colour) {
        this.colour = colour;
    }

    public Shape getShape() {
        return shape;
    }

    public void setShape(Shape shape) {
        this.shape = shape;
    }
}

We can inject a simple value into a bean, such as string, number, etc. We can also inject a reference to another bean. Here we define an example of other bean, the Rectangle bean that we will inject into the DrawingBean.

package org.kodejava.spring.core;

public interface Shape {
    /**
     * Draw a shape.
     */
    void draw();
}
package org.kodejava.spring.core;

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle.");
    }
}

Let’s create the Spring application configuration file that will register our beans into the Spring context. After that we just create a simple program to execute it.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="rectangle" class="org.kodejava.spring.core.Rectangle" />

    <bean id="drawingBean" class="org.kodejava.spring.core.DrawingBean">
        <property name="colour" value="Red" />
        <property name="shape" ref="rectangle" />
    </bean>

</beans>

In the configuration file above you can see that we use the property element to set a bean’s property. The name attribute is referring to the bean’s setter methods name, exclude the set prefix.

The value attribute of the property element is used to inject a simple value, such as string, int, etc. For injecting a reference to another bean we use the ref attribute instead.

package org.kodejava.spring.core;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DrawingBeanDemo {
    public static void main(String[] args) {
        try (var context = new ClassPathXmlApplicationContext("drawing-bean.xml")) {
            DrawingBean bean = (DrawingBean) context.getBean("drawingBean");
            bean.drawShape();
        }
    }
}

Here are the output of our example:

Drawing a rectangle.
The colour is Red.

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

Maven Central Maven Central Maven Central

How do I send email using Gmail via TLS?

The following example show you how to send email using Gmail SMTP via TLS connection. The username and password is used to authenticate you against the Gmail.

The configuration / properties used for connection to the Gmail SMTP is defined in the createConfiguration() method. The properties include information such as the SMTP host address, port number, etc.

To send email using Gmail via SSL see the following code snippet How do I send email using Gmail via SSL?.

Let’s see the code snippet below:

package org.kodejava.mail;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;

public class GmailSendEmailTLS {
    private static final String USERNAME = "[email protected]";
    private static final String PASSWORD = "password";

    public static void main(String[] args) throws Exception {
        // Email information such as from, to, subject and contents.
        String mailFrom = "[email protected]";
        String mailTo = "[email protected]";
        String mailSubject = "TLS - Gmail Send Email Demo";
        String mailText = "TLS - Gmail Send Email Demo";

        GmailSendEmailTLS gmail = new GmailSendEmailTLS();
        gmail.sendMail(mailFrom, mailTo, mailSubject, mailText);
    }

    private void sendMail(String mailFrom, String mailTo, String mailSubject,
                          String mailText) throws Exception {

        Properties config = createConfiguration();

        // Creates a mail session. We need to supply username and
        // password for Gmail authentication.
        Session session = Session.getInstance(config, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(
                        GmailSendEmailTLS.USERNAME,
                        GmailSendEmailTLS.PASSWORD
                );
            }
        });

        // Creates email message
        Message message = new MimeMessage(session);
        message.setSentDate(new Date());
        message.setFrom(new InternetAddress(mailFrom));
        message.setRecipient(Message.RecipientType.TO,
                new InternetAddress(mailTo));
        message.setSubject(mailSubject);
        message.setText(mailText);

        // Send a message
        Transport.send(message);
    }

    private Properties createConfiguration() {
        return new Properties() {{
            put("mail.smtp.auth", "true");
            put("mail.smtp.host", "smtp.gmail.com");
            put("mail.smtp.port", "587");
            put("mail.smtp.starttls.enable", "true");
            put("mail.smtp.ssl.protocols", "TLSv1.2");
        }};
    }
}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>javax.mail-api</artifactId>
        <version>1.5.6</version>
    </dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4.7</version>
    </dependency>
</dependencies>

Maven Central Maven Central

How do I send email using Gmail via SSL?

In another example you’ve seen how to send email using Gmail SMTP via TLS. See the following example How do I send email using Gmail via TLS?.

In this example you will use the SSL connection to connect to Gmail SMTP server. The difference with this is in the properties / configuration that we used to create the mail session object.

package org.kodejava.mail;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;

public class GmailSendEmailSSL {
    private static final String USERNAME = "[email protected]";
    private static final String PASSWORD = "password";

    public static void main(String[] args) throws Exception {
        // Email information such as from, to, subject and contents.
        String mailFrom = "[email protected]";
        String mailTo = "[email protected]";
        String mailSubject = "SSL - Gmail Send Email Demo";
        String mailText = "SSL - Gmail Send Email Demo";

        GmailSendEmailSSL gmail = new GmailSendEmailSSL();
        gmail.sendMail(mailFrom, mailTo, mailSubject, mailText);
    }

    private void sendMail(String mailFrom, String mailTo, String mailSubject,
                          String mailText) throws Exception {

        Properties config = createConfiguration();

        // Creates a mail session. We need to supply username and
        // password for Gmail authentication.
        Session session = Session.getInstance(config, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(
                        GmailSendEmailSSL.USERNAME,
                        GmailSendEmailSSL.PASSWORD
                );
            }
        });

        // Creates email message
        Message message = new MimeMessage(session);
        message.setSentDate(new Date());
        message.setFrom(new InternetAddress(mailFrom));
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(mailTo));
        message.setSubject(mailSubject);
        message.setText(mailText);

        // Send a message
        Transport.send(message);
    }

    private Properties createConfiguration() {
        return new Properties() {{
            put("mail.smtp.host", "smtp.gmail.com");
            put("mail.smtp.auth", "true");
            put("mail.smtp.port", "465");
            put("mail.smtp.socketFactory.port", "465");
            put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            put("mail.smtp.ssl.protocols", "TLSv1.2");
        }};
    }
}

There is a chance that you can get an error that tell you cannot connect to the smtp.gmail.com port 465. If this is the case please check your connection to the server using telnet command. The command is telnet smtp.gmail.com 465, and see if there is a reply.

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>javax.mail-api</artifactId>
        <version>1.5.6</version>
    </dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4.7</version>
    </dependency>
</dependencies>

Maven Central Maven Central

How do I debug application that uses JavaMail APIs?

To ask Java mail to print out a debug message when you run a Java mail program you can add the mail.debug and set the value to true into the properties used to create the session object.

The other way is to set the debug setting of the session using the session.setDebug() method and pass true as the parameter. This will also turn on the debug message in your Java mail program.

package org.kodejava.mail;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;

public class MailDebugDemo {
    public static void main(String[] args) {
        MailDebugDemo.sendMail("[email protected]", "[email protected]",
                "Debug Demo", "Mail Debug Demo");
    }

    private static void sendMail(String mailFrom, String mailTo, String mailSubject,
                                 String mailText) {
        Properties props = new Properties() {{
            put("mail.smtp.auth", "true");
            put("mail.smtp.host", "smtp.gmail.com");
            put("mail.transport.protocol", "smtp");
            put("mail.smtp.port", "587");
            put("mail.smtp.starttls.enable", "true");
            put("mail.smtp.ssl.protocols", "TLSv1.2");
            put("mail.debug", "true");
        }};

        // Creates a mail session. We need to supply username and
        // password for GMail authentication.
        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("[email protected]", "password");
            }
        });

        try {
            // Creates email message
            Message message = new MimeMessage(session);
            message.setSentDate(new Date());
            message.setFrom(new InternetAddress(mailFrom));
            message.setRecipient(Message.RecipientType.TO,
                    new InternetAddress(mailTo));
            message.setSubject(mailSubject);
            message.setText(mailText);

            // Send a message
            Transport.send(message);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }
}

Here is an example of debug information produce by the JavaMail API when sending an email using Gmail SMTP server.

DEBUG: JavaMail version 1.5.6
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false
220 smtp.gmail.com ESMTP b2sm4488826pgh.33 - gsmtp
DEBUG SMTP: connected to host "smtp.gmail.com", port: 587
...
...

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>javax.mail-api</artifactId>
        <version>1.5.6</version>
    </dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4.7</version>
    </dependency>
</dependencies>

Maven Central Maven Central