Sunday, 20 December 2020

Spring annotations


@Component is added at a class, meaning that this class will be scanned by the Spring container and loaded in the Spring context.  @Component is the most generic decoration. A @Service is a component; A @Controller is a component too. 

@Service means actually a specific @Component, which stands for a business logic layer.  So when a class is added with @Service, it will be scanned by Spring container and loaded in the context. 

@RestController  is also a specific @Component when a Spring context is initiated. These controllers will be instantiated and start waiting for the requests and making responses. 

@Autowired is specific to the Spring framework; it is equivalent to the Java @Injected 

@Configuration and its Relevant Annotations


@Configuration working with @Bean, @Value, @PropertySource, @ComponentScan and @Profile

@Configuration together with @Bean defines a bean blueprint, which tells a bean factory how to create a bean and its dependencies(DI).  In a simple word, it depicts a bean graph. 

@Configuration indicates a class, in which one or more @Beans methods are declared. 

What is a @Bean? @Bean is used to decorate a method. It tells Spring that this method is used to return an instantiated  @component or @Service. @Bean is used together with @Configuration class to tell Spring framework how to do DI. 



@Cofiguration working with externalized values

@Configuration class may need external env properties or other values defined in the other property files. 

Using  Environment API

Via Spring Environment injection, we may access properties. 
@Configuration
 public class AppConfig {

     @Autowired Environment env;

     @Bean
     public MyBean myBean() {
         MyBean myBean = new MyBean();
         myBean.setName(env.getProperty("bean.name"));
         return myBean;
     }
 }

Using Property Sources

Properties resolved via Environment reside in one or more "property source" objects; @Configuration may work with specific property files. 
@Configuration
@PropertySource("classpath:/com/acme/app.properties")
 public class AppConfig {

     @Inject Environment env;

     @Bean
     public MyBean myBean() {
         return new MyBean(env.getProperty("bean.name"));
     }
 }

Using Value Injection

Without bypass the Environment, externalized values may be injected into @Configuration via @Value.
@Configuration
 @PropertySource("classpath:/com/acme/app.properties")
 public class AppConfig {

     @Value("${bean.name}") String beanName;

     @Bean
     public MyBean myBean() {
         return new MyBean(beanName);
     }
 }

Specifying @Component Location

@ComponentScan configures component scanning directives for use with @Configuration classes. 

@Configuration
 @ComponentScan("com.acme.app.services")
 public class AppConfig {
     // various @Bean definitions ...
 }


?About proxyBeanMethods

By default  @Configuration(proxyBeanMethods=true); it specifies whether @Bean methods should get proxied in order to enforce bean lifecycle behaviour, e.g to return shared singleton bean instances even in direct @Bean method calls in user code. This feature requires method interception, implemented through a runtime-generated CGLIB subclass which comes with limitations such as configuration class and its methods not being allowed to declare final.  
public abstract boolean proxyBeanMethods


Sunday, 18 October 2020

Adding Extra Property Files in Spring and SpringBoot

Register a Properties File via Java Annotations

 @PropertySource annotation, it is introduced since Spring 3.1, and used in conjunction with Java-based configuration and the @Configuration annotation. 


Another useful way to register a new properties file is by using a placeholder, which allows us to dynamically select the right file at runtime. 

${envTarget:mysql}


Defining Multiple Property Locations

The  @PropertySource annotation is repeatable according to Java 8 conventions. We can define multiple properties files and their locations. 

We can specify an array of @PropertySource; this works in any Java version.

Using/Injecting Properties

Injecting a property using the @Value annotation.

?? specify a default value for the property. 

We can obtain the value of a property using the Environment API
@Autowired
private Environment env; 
...
dataSource.setUrl(env.getProperty("jdbc.rul));


Properties with Spring Boot

Default Property File


This new support involves less configuration compared to standard Spring. 

application.properties: the Default Property File; doesn't need any arrangement


Environment-Specific Properties File

If we need to target different environments, application-environment.properties file in the src/main/resources directory, and then set a Spring profile with the same environment name. 

if we define a "staging" environment, we then have to define a stagging profile, and then application-stagging.properties. 

This env file will be loaded and will take precedence over the default property file. 


Test-Specific Properties File

Spring boot looks for test specific files in our src/test/resources directory during a test run. Again, default properties will still be injectable as normal but will be overridden by these test specific properties if there is a collision. 


@Runwith(SpringRunner.class)
@TestPropertySource("/foo.properties")


if we don't want to use a file, directly specify names and values.
@TestPropertySource(properties={"foo=bar"})

or it can achieve the same using
@RunWith(SpringRunner.class)
@SpringBootTest(
properties={"foo=bar"},classes=SpringBootPropertiesTestApplication.class)
)


Hierarchical Properties

we can mapping a group of properties from a file into a POJO, using @ConfiguartionProperties annotation.

Properties from Command Line Arguments

java -jar app.jar --property="value"

or via system properties, which are provided before the -jar command rather than after it
java -Dproperty.name="value" -jar app.jar

Properties from Environment Variables

export name=value
java -jar app.jar







 




 



Friday, 21 August 2020

Caused by: org.hibernate.TransientObjectException:

 Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.ynz.demobasicauthentication.entities.User



I met the same Exception, as handling many to many relationships.

my case is a user has many roles, while a role has many users.

the exception Is due to as persisting user, but its associated roles that haven’t been saved in the base; so the PK is not present. so the relationships cannot be built up.


solution:   I added cascade type then the exception was solved. 

@ManyToMany(cascade = CascadeType.PERSIST)








Thursday, 6 August 2020

Spring Boot Database Initialisation

Initialise a database using Hibernate

spring.jpa.hibernate.ddl-auto= [none, validate, update, create-drop] controls how to generate database tables. 

  • create: Hibernate first drops existing tables, then creates new tables.
  • update: Comparing with existing tables or columns in the database, and update the existing according to the diff. It never deletes the existing tables or columns even if they are no more required by the application.  
  • create-drop: similar to create, with the addition that Hibernate will drop the database after all operations are completed. Typically used for unit testing.  
  • validate: Hibernate only validate whether the tables and columns exist, otherwise it throws an exception.
  • none: this value effectively turns off the DDL generation. 

Spring boot may recognize database type and gives default value. 

If it finds that it is an embedded database: spring.jpa.hibernate.ddl-auto=create-drop; 
so maybe you need to turn it off; otherwise, hibernate will automatically create the schema in line with entities. 

If it finds that it is a real database, then spring.jpa.hibernate.ddl-auto=none; 
It will automatically find schema.sql and data.sql to create tables and populating data. 


spring.jpa.show-sql=true displaying SQL in the console. 
spring.jpa.properties.hibernate.format_sql=true Formatting the SQL

//doesn't work
spring.datasource.initialize=false turn off initialising using scripts.  


Spring Boot can automatically create the schema (DDL scripts) of your DataSource and initialize it (DML scripts). It loads SQL from the standard root classpath locations: schema.sql and data.sql, respectively. In addition, Spring Boot processes the schema-${platform}.sql and data-${platform}.sql files (if present), where platform is the value of spring.datasource.platform. This allows you to switch to database-specific scripts if necessary. For example, you might choose to set it to the vendor name of the database (hsqldb, h2, oracle, mysql, postgresql, and so on).


You can set spring.jpa.hibernate.ddl-auto explicitly and the standard Hibernate property values are none, validate, update, create, and create-drop. Spring Boot chooses a default value for you based on whether it thinks your database is embedded. It defaults to create-drop if no schema manager has been detected or none in all other cases. An embedded database is detected by looking at the Connection type. hsqldb, h2, and derby are embedded, and others are not. Be careful when switching from in-memory to a ‘real’ database that you do not make assumptions about the existence of the tables and data in the new platform. You either have to set ddl-auto explicitly or use one of the other mechanisms to initialize the database.


Spring provides a JPA-specific property which Hibernate uses for DDL generation: spring.jpa.hibernate.ddl-auto.

The standard Hibernate property values are: create, update, create-drop, validate and none:

create – Hibernate first drops existing tables, then creates new tables
update – the object model created based on the mappings (annotations or XML) is compared with the existing schema, and then Hibernate updates the schema according to the diff. It never deletes the existing tables or columns even if they are no more required by the application
create-drop – similar to create, with the addition that Hibernate will drop the database after all operations are completed. Typically used for unit testing
validate – Hibernate only validates whether the tables and columns exist, otherwise it throws an exception
none – this value effectively turns off the DDL generation
Spring Boot internally defaults this parameter value to create-drop if no schema manager has been detected, otherwise none for all other cases.



Can Jackson Deserialize Java Time ZonedDateTime

Yes, but must include JSR310. Thus ZonedDateTime can be deserialized directly from JSON response to POJO field. <dependency> <g...