The application that is generated will not feature any frontend. Again, the invoice service is a Spring Boot-based application. The security features are configured in MicroserviceSecurityConfiguration.java.
Ignore all the frontend related requests, so whenever a user tries to reach any frontend-related resources such as HTML, CSS, and JS, the request will be ignored by the invoice service:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/app/**/*.{js,html}")
.antMatchers("/bower_components/**")
.antMatchers("/i18n/**")
.antMatchers("/content/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/test/**")
.antMatchers("/h2-console/**");
}
Since the services are independent, they can be deployed and run on another server with a different IP address. This requires us to disable CSRF (Cross Site Request Forgery) by default. We will also enable the STATELESS session policy in session management. This makes our application unable to create or maintain any sessions. Every request is authenticated and authorized based on the token.
We will also use the STATELESS session policy in session management. This is the strictest session policy available. This will not allow our application to generate a session, and so our requests have to have the (time-bound) tokens attached to each and every request. This enhances the security of our services. Their stateless constraint is another advantage of using REST APIs.
Then, all API-related requests and Swagger resources should be allowed once the request is authorized (based on the JWT token):
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/swagger-resources/configuration/ui").permitAll()
.and()
.apply(securityConfigurerAdapter());
}
On the resource side, in bootstrap.yml, we have defined the registry-related information.
Our current microservice application uses the JHipster registry as the registry service in order to register and deregister their existence in a heartbeat. We need to provide the password of our registry service with which the application can connect to the registry service:
jhipster:
registry:
password: admin
Also, the name of the Spring Boot service and the default Spring Cloud Config parameters are enabled in the bootstrap.yml. We have also added the URI that we have to connect in order to fetch the configuration of the registry service:
spring:
application:
name: invoice
...
cloud:
config:
fail-fast: false # if not in "prod" profile, do not force to use Spring Cloud Config
uri: http://admin:${jhipster.registry.password}@localhost:8761/config
# name of the config server's property source (file.yml) that we want to use
name: invoice
...
Similar to the gateway, the rest of the service-related configurations are done in the application.yml file.
The Eureka configuration is exactly the same as in the gateway application. All the generated applications will have a similar Eureka configuration:
eureka:
client:
enabled: true
healthcheck:
enabled: true
fetch-registry: true
register-with-eureka: true
instance-info-replication-interval-seconds: 10
registry-fetch-interval-seconds: 10
instance:
appname: invoice
instanceId: invoice:${spring.application.instance-id:${random.value}}
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 10
status-page-url-path: ${management.context-path}/info
health-check-url-path: ${management.context-path}/health
metadata-map:
zone: primary # This is needed for the load balancer
profile: ${spring.profiles.active}
version: ${info.project.version}
The database and JPA configurations are made:
spring:
profiles:
active: dev
...
datasource:
type: <connector jar>
url: <db url>
username: <username>
password: <password>
...
jpa:
database-platform: <DB platform>
database: <H2 or MySQL or any SQL database>
show-sql: true
properties:
hibernate.id.new_generator_mappings: true
hibernate.cache.use_second_level_cache: true
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: true
hibernate.cache.region.factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
hibernate.cache.hazelcast.instance_name: invoice
hibernate.cache.use_minimal_puts: true
hibernate.cache.hazelcast.use_lite_member: true
The rest of the configurations remain similar to what was generated in the gateway application, and they can be tweaked or customized based on your requirements.
Now, we can boot up the application alongside the gateway application and registry service. Since the application tries to connect to the registry service first, if there is no registry service available at the specified location, then the application will not know where to connect and whom to respond to.
Thus, the invoice service is generated. Now, we can generate a notification service with NoSQL as the backend database.