Following example shows how prototype bean can contain a session information.
Example
This example creates a registration form simulator. It asks user to enter registration information on command line. It does some validations on entered values and keep the same prototype bean session (UserRegistrationBean) unless user successfully correct all validation errors.
A POJO contains user info
package com.logicbig.example.service;
public class UserInfo {
private String email;
private String password;
.............
}
User info Validator
package com.logicbig.example.bean;
import java.util.regex.Pattern;
public class UserRegistrationValidator {
private static final Pattern VALID_EMAIL_PATTERN =
Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$",
Pattern.CASE_INSENSITIVE);
private static final Pattern VALID_PASSWORD_PATTERN =
Pattern.compile("^[a-zA-Z0-9]{6,}$");
public String validateEmail(String email){
if (!VALID_EMAIL_PATTERN.matcher(email).matches()) {
return "Not a valid email: " + email;
}
return null;
}
public String validatePassword(String password){
if (!VALID_PASSWORD_PATTERN.matcher(password).matches()) {
return "Not a valid password. The password should be alphanumeric and " +
"at least 6 characters long ";
}
return null;
}
}
Registration Service
package com.logicbig.example.service;
public interface RegistrationService {
void register(UserInfo userInfo);
}
Registration Service implementation
public class RegistrationServiceImpl implements RegistrationService {
@Override
public void register(UserInfo userInfo) {
//todo: save user in a database
}
}
Registration service client bean
package com.logicbig.example.bean;
import com.logicbig.example.service.UserInfo;
import java.util.Map;
public interface UserRegistrationBean {
public static String KEY_EMAIL = "email";
public static String KEY_PASSWORD = "password";
void setUserInfo(UserInfo userInfo);
Map<String, String> validate();
void register();
}
package com.logicbig.example.bean;
import com.logicbig.example.service.RegistrationService;
import com.logicbig.example.service.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import jakarta.annotation.PostConstruct;
import java.util.LinkedHashMap;
import java.util.Map;
public class UserRegistrationBeanImpl implements UserRegistrationBean {
@Autowired
private RegistrationService registrationService;
@Autowired
private UserRegistrationValidator validator;
private UserInfo userInfo;
@Override
public void setUserInfo (UserInfo userInfo) {
this.userInfo = userInfo;
}
@Override
public Map<String, String> validate () {
if (userInfo == null) {
throw new RuntimeException("UserInfo must be set before calling validate method");
}
Map<String, String> errors = new LinkedHashMap<>();
String errorMessage = validator.validateEmail(userInfo.getEmail());
if (errorMessage != null) {
errors.put(KEY_EMAIL, errorMessage);
}
errorMessage = validator.validatePassword(userInfo.getPassword());
if (errorMessage != null) {
errors.put(KEY_PASSWORD, errorMessage);
}
return errors;
}
@Override
public void register () {
registrationService.register(userInfo);
}
}
Defining beans
package com.logicbig.example;
import com.logicbig.example.bean.UserRegistrationBean;
import com.logicbig.example.bean.UserRegistrationBeanImpl;
import com.logicbig.example.bean.UserRegistrationValidator;
import com.logicbig.example.service.RegistrationService;
import com.logicbig.example.service.RegistrationServiceImpl;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class Config {
@Bean
public UserRegistrationValidator validator () {
return new UserRegistrationValidator();
}
@Bean
public RegistrationService registrationService () {
return new RegistrationServiceImpl();
}
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean
public UserRegistrationBean userRegistrationBean () {
return new UserRegistrationBeanImpl();
}
}
Main class
package com.logicbig.example;
import com.logicbig.example.bean.UserRegistrationBean;
import com.logicbig.example.service.UserInfo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Map;
import java.util.Scanner;
public class AppMain {
private final PrintStream printStream;
private Scanner scanner;
public AppMain(InputStream inputStream, PrintStream printStream) {
this.scanner = new Scanner(inputStream);
this.printStream = printStream;
}
public static void main(String[] args) {
AppMain appMain = new AppMain(System.in, System.out);
appMain.start();
}
public void start() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(Config.class);
UserRegistrationBean registrationBean = context.getBean(UserRegistrationBean.class);
while (true) {
printStream.println("UserRegistrationBean, instance: " + System.identityHashCode(registrationBean));
printStream.println("Enter new user. Enter exit to terminate");
boolean exit = registerUser(registrationBean);
if (exit) {
break;
}
registrationBean = context.getBean(UserRegistrationBean.class);
}
}
private boolean registerUser(UserRegistrationBean registrationBean) {
UserInfo userInfo = new UserInfo();
registrationBean.setUserInfo(userInfo);
Map<String, String> errors = null;
while (errors == null || errors.size() > 0) {
if (errors != null) {
printStream.println("Errors : " + errors.values() + "\n");
printStream.println("Please enter exit to terminate");
}
if (errors == null || errors.containsKey(UserRegistrationBean.KEY_EMAIL)) {
String email = getUserInput("Enter Email");
if (email == null) {
return true;
}
userInfo.setEmail(email);
}
if (errors == null || errors.containsKey(UserRegistrationBean.KEY_PASSWORD)) {
String password = getUserInput("Enter Password");
if (password == null) {
return true;
}
userInfo.setPassword(password);
}
errors = registrationBean.validate();
}
registrationBean.register();
printStream.println("User has been registered successfully: "+userInfo);
return false;
}
public String getUserInput(String instruction) {
printStream.print(instruction + ">");
String s = scanner.nextLine();
if ("exit".equals(s)) {
return null;
}
return s;
}
}
Output
UserRegistrationBean, instance: 1089504328
Enter new user. Enter exit to terminate
Enter Email>xyz
Enter Password>123
Errors : [Not a valid email: xyz, Not a valid password. The password should be alphanumeric and at least 6 characters long ]
Please enter exit to terminate
Enter Email>joe@example.com
Enter Password>123456
User has been registered successfully: UserInfo{email='joe@example.com', password='123456'}
UserRegistrationBean, instance: 660879561
Enter new user. Enter exit to terminate
Enter Email>joe2@example.com
Enter Password>987654
User has been registered successfully: UserInfo{email='joe2@example.com', password='987654'}
UserRegistrationBean, instance: 1485697819
Enter new user. Enter exit to terminate
Enter Email>exit
Note that how new instance of UserRegistrationBean (the prototype bean) is created on each call of context.getBean(UserRegistrationBean.class)
Example ProjectDependencies and Technologies Used: - spring-context 6.1.2 (Spring Context)
Version Compatibility: 3.2.3.RELEASE - 6.1.2 Version compatibilities of spring-context with this example: Versions in green have been tested.
- jakarta.jakartaee-api 10.0.0 (Eclipse Foundation)
- junit 4.13.2 (JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck)
- JDK 17
- Maven 3.8.1
|