Backend for frontend BFF — Step 2
This story is part of a series “Initial Commit till Running on Cloud”.
Now that we know something about our repository let’s start creating actual projects that can be packaged, dockerized and deployed to cloud.
I have chosen the following to do this perfect product. You can replace the frameworks/languages/software with your favorites but in the end the result should more or less be the same (I can’t guarantee you that though). So our stellar cast for this movie is…
Javascript — Frontend language
Java — Backend language
Angular — Frontend framework
Spring — Backend framework
MongoDB — Database
Kafka — Messaging system
AWS — Cloud Provider
First we will be creating a BFF project which will contain both Angular frontend code and Java backend code. Down the line it will connect to rest of our microservices ecosystem. This BFF application will pack both Java backend and Angular frontend code inside a single web application which runs as a JVM jar. This approach can be replaced by an Express JS application running in Node.
I have created awesome-app-bff repository in Github so that you can follow the code step by step from the commits.
Maven configuration
First I have added a pom.xml which contains spring-boot-starter-parent, spring-boot-starter-web, spring-boot-starter-security, spring-boot-starter-data-mongodb, spring-session-data-mongodb as some of the main dependencies.
As this is the User facing frontend application, it will contain a login page which will be backed by spring security framework. Also Spring session is a special library which helps us in managing distributed user sessions as we will deploy multiple instances of the same BFF for high availability in the cloud. Spring session is the reason we need mongodb starter in BFF as sessions will be stored in Mongo DB once user logs in. This record will be queried by other instances to check if a user has already logged in via one of our BFF instances.
Spring Boot Application
Next we will add a simple spring boot application under src folder.
AwesomeAppBffApplication at this point contains just the standard Spring boot application class.
@SpringBootApplication
public class AwesomeAppBffApplication {
public static void main(String[] args) {
SpringApplication.run(AwesomeAppBffApplication.class, args);
}
}
UserService class acts as a service class to fetch registered users during login. This will be completed once we have created a user-microservice.
@Slf4j
@Service
public class UserService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
throw new UsernameNotFoundException(username);
}
}
CommonSecurityConfig contains common beans which will be used in SecurityConfig. I want my bean configurations to be clean :)
@Configuration
public class CommonSecurityConfig {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
And finally our SecurityConfig class which contains security configuration of project. You can see that I have injected CommonSecurityConfig beans here.
@Configuration
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final BCryptPasswordEncoder passwordEncoder;
private final UserDetailsService userService;
private final AuthenticationManagerBuilder authenticationBuilder;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.formLogin()
.and()
.authorizeRequests()
.antMatchers("/secured/**")
.authenticated()
.and()
.authorizeRequests()
.and()
.httpBasic();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
authenticationBuilder.userDetailsService(userService).passwordEncoder(passwordEncoder);
return super.authenticationManagerBean();
}
}
EnableGlobalMethodSecurity protects endpoints with Role based checks. FormLogin for a temporary html login page and the system uses Basic HTTP to authenticate users which in my opinion is the apt authentication for BFF. You don’t want to complicate things with Oauth for frontend.
The only endpoint which is protected by spring security with this configuration is the /secured. We will get back to that when the application grows.
spring.data.mongodb.uri: mongodb+srv://awesome-app-bff-admin:password@test-orvxq.mongodb.net/awesome-app-bff
spring.session.store-type: mongodb
server.port: 80
application.yml contains the above 3 properties. As it is a BFF I have overridden the port to 80.
MongoDB Atlas is a fantastic cloud DB provider which we will use in this project and once we are done I will also show how to peer our AWS VPC with MongoDB Atlas VPC. So create your own account and get your DB uri.
run mvn clean install and you will get the jar inside target folder.
awesome-app-bff-1.0.0-SNAPSHOT.jar
To find if everything went fine you can run AwesomeAppBffApplication and check your logs. You should be able to hit localhost and see Spring error page.
Congratulations you are now ready to face all the errors you might get to finish this project.
Next stop Frontend.
Going good? Please read the next part of this series. Also kindly leave your feedback :)