diff options
Diffstat (limited to 'spring-framework')
129 files changed, 3638 insertions, 0 deletions
diff --git a/spring-framework/00-build-all/.gitignore b/spring-framework/00-build-all/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/00-build-all/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/00-build-all/pom.xml b/spring-framework/00-build-all/pom.xml new file mode 100644 index 0000000..2f094c8 --- /dev/null +++ b/spring-framework/00-build-all/pom.xml @@ -0,0 +1,24 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.example.spring</groupId> + <artifactId>00-build-all</artifactId> + <version>0.0.1-SNAPSHOT</version> + + <packaging>pom</packaging> + + <description>A module to facilitate usage of reactor.</description> + + <modules> + <module>../00-config</module> + + + + + <module>../01-basic-xml-config</module> + <module>../02-basic-annotation-config</module> + <module>../03-basic-component-scan</module> + <module>../04-basic-no-xml</module> + <module>../05-simple-gui</module> + </modules> +</project> diff --git a/spring-framework/00-config-webapps/.gitignore b/spring-framework/00-config-webapps/.gitignore new file mode 100644 index 0000000..e285fe2 --- /dev/null +++ b/spring-framework/00-config-webapps/.gitignore @@ -0,0 +1,6 @@ +/.classpath +/.project +/.settings/ +/.metadata/ +/target/ +/pom.xml diff --git a/spring-framework/00-config-webapps/README b/spring-framework/00-config-webapps/README new file mode 100644 index 0000000..6786e0f --- /dev/null +++ b/spring-framework/00-config-webapps/README @@ -0,0 +1,9 @@ +Run this command to clean and package the application, start Tomcat and deploy the application: + + mvn clean package cargo:run + +Application will be accessible via http://localhost:8080/<maven project artifact id>/ + +To redeploy the application, run the below Maven command from a different terminal while being inside the Maven project directory: + + mvn package cargo:redeploy diff --git a/spring-framework/00-config/.gitignore b/spring-framework/00-config/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/00-config/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/00-config/pom.xml b/spring-framework/00-config/pom.xml new file mode 100644 index 0000000..be77ab6 --- /dev/null +++ b/spring-framework/00-config/pom.xml @@ -0,0 +1,99 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>pom</packaging> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + + <!-- Versions of dependencies --> + <springVersion>7.0.7</springVersion> + <aspectjVersion>1.9.25.1</aspectjVersion> + + <commonsDBCP2Version>2.14.0</commonsDBCP2Version> + <mariadbClientVersion>3.5.8</mariadbClientVersion> + </properties> + + <build> + <plugins> + <!-- Find the latest versions of plugins available by running "mvn versions:display-plugin-updates" --> + <!-- + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>versions-maven-plugin</artifactId> + <version>2.7</version> + <configuration> + <generateBackupPoms>false</generateBackupPoms> + </configuration> + </plugin> + --> + + <!-- Set Java SE version --> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.15.0</version> + <configuration> + <release>25</release> + </configuration> + </plugin> + + <!-- Specify main class in generated Jar --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.5.0</version> + <configuration> + <archive> + <manifest> + <mainClass>com.example.spring.App</mainClass> + </manifest> + </archive> + </configuration> + </plugin> + + <!-- Specify main class to execute from command line: mvn exec:java --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>3.6.3</version> + <executions> + <execution> + <goals> + <goal>java</goal> + </goals> + </execution> + </executions> + <configuration> + <mainClass>com.example.spring.App</mainClass> + + <!-- We may prefer to execute as 'mvn exec:exec' to get the execution + happen in new JVM. --> + <!-- https://www.mojohaus.org/exec-maven-plugin/examples/example-exec-for-java-programs.html --> + <executable>java</executable> + <arguments> + <argument>-classpath</argument> + <!-- automatically creates the classpath using all project dependencies, + also adding the project build directory --> + <classpath /> + <argument>com.example.spring.App</argument> + </arguments> + </configuration> + </plugin> + + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>${springVersion}</version> + </dependency> + </dependencies> + +</project> diff --git a/spring-framework/01-basic-xml-config/.gitignore b/spring-framework/01-basic-xml-config/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/01-basic-xml-config/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/01-basic-xml-config/pom.xml b/spring-framework/01-basic-xml-config/pom.xml new file mode 100644 index 0000000..baddc63 --- /dev/null +++ b/spring-framework/01-basic-xml-config/pom.xml @@ -0,0 +1,16 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>basic-xml-config</artifactId> + <packaging>jar</packaging> + +</project> diff --git a/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/App.java b/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..d5771a7 --- /dev/null +++ b/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/App.java @@ -0,0 +1,18 @@ +package com.example.spring; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class App { + public static void main(String[] args) { + + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + MathsUser mathsUser = ctx.getBean(MathsUser.class); + + mathsUser.doTask(); + + ctx.close(); + } + +} diff --git a/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/Maths.java b/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/Maths.java new file mode 100644 index 0000000..b42d32d --- /dev/null +++ b/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/Maths.java @@ -0,0 +1,19 @@ +package com.example.spring; + +public class Maths { + + private int b; + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + + + public int add(int a) { + return a + b; + } +} diff --git a/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/MathsUser.java b/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/MathsUser.java new file mode 100644 index 0000000..0e4cecf --- /dev/null +++ b/spring-framework/01-basic-xml-config/src/main/java/com/example/spring/MathsUser.java @@ -0,0 +1,16 @@ +package com.example.spring; + +public class MathsUser { + + private Maths maths; + + public void setMaths(Maths maths) { + this.maths = maths; + } + + public void doTask() { + int result = maths.add(10); + + System.out.println(result); + } +} diff --git a/spring-framework/01-basic-xml-config/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/01-basic-xml-config/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..48a3ecc --- /dev/null +++ b/spring-framework/01-basic-xml-config/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,23 @@ +<?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"> + + <!-- + Maths maths = new Maths(); + maths.setB(100); + --> + <bean id="maths" class="com.example.spring.Maths"> + <property name="b" value="100"></property> + </bean> + + <!-- + MathsUser mathsUser = new MathsUser(); + mathsUser.setMaths(maths); + --> + <bean id="mathsUser" class="com.example.spring.MathsUser"> + <property name="maths" ref="maths"></property> + </bean> + +</beans> diff --git a/spring-framework/02-basic-annotation-config/.gitignore b/spring-framework/02-basic-annotation-config/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/02-basic-annotation-config/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/02-basic-annotation-config/pom.xml b/spring-framework/02-basic-annotation-config/pom.xml new file mode 100644 index 0000000..083aa1e --- /dev/null +++ b/spring-framework/02-basic-annotation-config/pom.xml @@ -0,0 +1,16 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>basic-annotation-config</artifactId> + <packaging>jar</packaging> + +</project> diff --git a/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/App.java b/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..d5771a7 --- /dev/null +++ b/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/App.java @@ -0,0 +1,18 @@ +package com.example.spring; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class App { + public static void main(String[] args) { + + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + MathsUser mathsUser = ctx.getBean(MathsUser.class); + + mathsUser.doTask(); + + ctx.close(); + } + +} diff --git a/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/Maths.java b/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/Maths.java new file mode 100644 index 0000000..b42d32d --- /dev/null +++ b/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/Maths.java @@ -0,0 +1,19 @@ +package com.example.spring; + +public class Maths { + + private int b; + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + + + public int add(int a) { + return a + b; + } +} diff --git a/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/MathsUser.java b/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/MathsUser.java new file mode 100644 index 0000000..b8015f0 --- /dev/null +++ b/spring-framework/02-basic-annotation-config/src/main/java/com/example/spring/MathsUser.java @@ -0,0 +1,15 @@ +package com.example.spring; + +import org.springframework.beans.factory.annotation.Autowired; + +public class MathsUser { + + @Autowired + private Maths maths; + + public void doTask() { + int result = maths.add(10); + + System.out.println(result); + } +} diff --git a/spring-framework/02-basic-annotation-config/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/02-basic-annotation-config/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..837558b --- /dev/null +++ b/spring-framework/02-basic-annotation-config/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:context="http://www.springframework.org/schema/context" + 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 + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:annotation-config /> + + <bean id="maths" class="com.example.spring.Maths"> + <property name="b" value="100"></property> + </bean> + + <bean id="mathsUser" class="com.example.spring.MathsUser"> + </bean> +</beans> diff --git a/spring-framework/03-basic-component-scan/.gitignore b/spring-framework/03-basic-component-scan/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/03-basic-component-scan/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/03-basic-component-scan/pom.xml b/spring-framework/03-basic-component-scan/pom.xml new file mode 100644 index 0000000..8dd7ef8 --- /dev/null +++ b/spring-framework/03-basic-component-scan/pom.xml @@ -0,0 +1,16 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>basic-component-scan</artifactId> + <packaging>jar</packaging> + +</project> diff --git a/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/App.java b/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..d5771a7 --- /dev/null +++ b/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/App.java @@ -0,0 +1,18 @@ +package com.example.spring; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class App { + public static void main(String[] args) { + + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + MathsUser mathsUser = ctx.getBean(MathsUser.class); + + mathsUser.doTask(); + + ctx.close(); + } + +} diff --git a/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/Maths.java b/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/Maths.java new file mode 100644 index 0000000..3a0b822 --- /dev/null +++ b/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/Maths.java @@ -0,0 +1,24 @@ +package com.example.spring; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class Maths { + + @Value("100") + private int b; + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + + + public int add(int a) { + return a + b; + } +} diff --git a/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/MathsUser.java b/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/MathsUser.java new file mode 100644 index 0000000..90a448d --- /dev/null +++ b/spring-framework/03-basic-component-scan/src/main/java/com/example/spring/MathsUser.java @@ -0,0 +1,17 @@ +package com.example.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class MathsUser { + + @Autowired + private Maths maths; + + public void doTask() { + int result = maths.add(10); + + System.out.println(result); + } +} diff --git a/spring-framework/03-basic-component-scan/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/03-basic-component-scan/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..bca3a41 --- /dev/null +++ b/spring-framework/03-basic-component-scan/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:context="http://www.springframework.org/schema/context" + 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 + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:annotation-config/> + + <context:component-scan base-package="com.example.spring"/> + +</beans> diff --git a/spring-framework/04-basic-no-xml-java-configuration/.gitignore b/spring-framework/04-basic-no-xml-java-configuration/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/04-basic-no-xml-java-configuration/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/04-basic-no-xml-java-configuration/README b/spring-framework/04-basic-no-xml-java-configuration/README new file mode 100644 index 0000000..5e8720d --- /dev/null +++ b/spring-framework/04-basic-no-xml-java-configuration/README @@ -0,0 +1,12 @@ +This project illustrates how a Java class can be made to describe the Spring configuration +where the objects returned by methods in the class are made to be the Spring beans. + +The class is annotated with @Configuration which indicates that the primary purpose of the +class is to act as a source of bean definitions. + +@Bean is used with a method to indicate that the method instantiates, configures, and +initializes a new object to be managed by the Spring IoC container. It plays the same role +as the <bean/> element. + +It is not necessary for the classes from which beans are instantiated to have annotations +like @Component or @Autowired since the @Bean annotated methods perform the configuration. diff --git a/spring-framework/04-basic-no-xml-java-configuration/pom.xml b/spring-framework/04-basic-no-xml-java-configuration/pom.xml new file mode 100644 index 0000000..b76e1f0 --- /dev/null +++ b/spring-framework/04-basic-no-xml-java-configuration/pom.xml @@ -0,0 +1,16 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>basic-no-xml-java-configuration</artifactId> + <packaging>jar</packaging> + +</project> diff --git a/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/App.java b/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..1e613c6 --- /dev/null +++ b/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/App.java @@ -0,0 +1,50 @@ +package com.example.spring; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class App { + + public static void main(String[] args) { + @SuppressWarnings("resource") + ApplicationContext ctx = new AnnotationConfigApplicationContext(App.class); + + MathsUser mathsUser = ctx.getBean(MathsUser.class); + + mathsUser.doTask(); + } + + @Bean + public Maths maths() { + Maths maths = new Maths(); + maths.setB(100); + + return maths; + } + + @Bean + public MathsUser mathsUser() { + MathsUser mathsUser = new MathsUser(); + + /* + * What would the maths() return? Would it be the Spring managed bean or what + * would be returned when the maths() method is directly invoked? + * + * @Bean can be used with classes annotated with @Component tool. + * + * In a class annotated with @Configuration, maths() return the Spring managed bean. + * + * In a class annotated with @Component, what is returned by maths() is not the + * Spring managed bean, but what would be returned when the maths() method is directly invoked. + * + * For more details, look at the 'Full @Configuration vs “lite” @Bean mode?' description + * found in the 'Core Technologies' section of the Spring Framework Reference documentation. + */ + mathsUser.setMaths(maths()); + + return mathsUser; + } +}
\ No newline at end of file diff --git a/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/Maths.java b/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/Maths.java new file mode 100644 index 0000000..b42d32d --- /dev/null +++ b/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/Maths.java @@ -0,0 +1,19 @@ +package com.example.spring; + +public class Maths { + + private int b; + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + + + public int add(int a) { + return a + b; + } +} diff --git a/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/MathsUser.java b/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/MathsUser.java new file mode 100644 index 0000000..aba1836 --- /dev/null +++ b/spring-framework/04-basic-no-xml-java-configuration/src/main/java/com/example/spring/MathsUser.java @@ -0,0 +1,16 @@ +package com.example.spring; + +public class MathsUser { + + private Maths maths; + + public void setMaths(Maths maths) { + this.maths = maths; + } + + public void doTask() { + int result = maths.add(10); + + System.out.println(result); + } +} diff --git a/spring-framework/04-basic-no-xml/.gitignore b/spring-framework/04-basic-no-xml/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/04-basic-no-xml/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/04-basic-no-xml/pom.xml b/spring-framework/04-basic-no-xml/pom.xml new file mode 100644 index 0000000..90e9939 --- /dev/null +++ b/spring-framework/04-basic-no-xml/pom.xml @@ -0,0 +1,16 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>basic-no-xml</artifactId> + <packaging>jar</packaging> + +</project> diff --git a/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/App.java b/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..14c2599 --- /dev/null +++ b/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/App.java @@ -0,0 +1,39 @@ +package com.example.spring; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = "com.example.spring") +public class App { + + public static void main(String[] args) { + + @SuppressWarnings("resource") + ApplicationContext ctx = + new AnnotationConfigApplicationContext(App.class); + + MathsUser mathsUser = ctx.getBean(MathsUser.class); + + mathsUser.doTask(); + + } + + // Another way + public static void main2(String[] args) { + + + @SuppressWarnings("resource") + AnnotationConfigApplicationContext ctx = + new AnnotationConfigApplicationContext(); + ctx.scan("com.example.spring"); + ctx.refresh(); + + MathsUser mathsUser = ctx.getBean(MathsUser.class); + + mathsUser.doTask(); + + } +} diff --git a/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/Maths.java b/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/Maths.java new file mode 100644 index 0000000..8825be7 --- /dev/null +++ b/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/Maths.java @@ -0,0 +1,24 @@ +package com.example.spring; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class Maths { + + @Value("10") + private int b; + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + + + public int add(int a) { + return a + b; + } +} diff --git a/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/MathsUser.java b/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/MathsUser.java new file mode 100644 index 0000000..90a448d --- /dev/null +++ b/spring-framework/04-basic-no-xml/src/main/java/com/example/spring/MathsUser.java @@ -0,0 +1,17 @@ +package com.example.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class MathsUser { + + @Autowired + private Maths maths; + + public void doTask() { + int result = maths.add(10); + + System.out.println(result); + } +} diff --git a/spring-framework/05-simple-gui/.gitignore b/spring-framework/05-simple-gui/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/05-simple-gui/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/05-simple-gui/pom.xml b/spring-framework/05-simple-gui/pom.xml new file mode 100644 index 0000000..647732b --- /dev/null +++ b/spring-framework/05-simple-gui/pom.xml @@ -0,0 +1,16 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>simple-gui</artifactId> + <packaging>jar</packaging> + +</project> diff --git a/spring-framework/05-simple-gui/src/main/java/com/example/spring/App.java b/spring-framework/05-simple-gui/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..ed8b310 --- /dev/null +++ b/spring-framework/05-simple-gui/src/main/java/com/example/spring/App.java @@ -0,0 +1,15 @@ +package com.example.spring; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class App { + public static void main(String[] args) { + + @SuppressWarnings({ "resource", "unused" }) + ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + } + +} diff --git a/spring-framework/05-simple-gui/src/main/java/com/example/spring/logic/Maths.java b/spring-framework/05-simple-gui/src/main/java/com/example/spring/logic/Maths.java new file mode 100644 index 0000000..774afe1 --- /dev/null +++ b/spring-framework/05-simple-gui/src/main/java/com/example/spring/logic/Maths.java @@ -0,0 +1,7 @@ +package com.example.spring.logic; + +public interface Maths { + + public double add(double a, double b); + +}
\ No newline at end of file diff --git a/spring-framework/05-simple-gui/src/main/java/com/example/spring/logic/MathsImpl.java b/spring-framework/05-simple-gui/src/main/java/com/example/spring/logic/MathsImpl.java new file mode 100644 index 0000000..7d11543 --- /dev/null +++ b/spring-framework/05-simple-gui/src/main/java/com/example/spring/logic/MathsImpl.java @@ -0,0 +1,10 @@ +package com.example.spring.logic; + + +public class MathsImpl implements Maths { + + @Override + public double add(double a, double b) { + return a + b; + } +} diff --git a/spring-framework/05-simple-gui/src/main/java/com/example/spring/ui/MyAppFrame.java b/spring-framework/05-simple-gui/src/main/java/com/example/spring/ui/MyAppFrame.java new file mode 100644 index 0000000..3b42ca3 --- /dev/null +++ b/spring-framework/05-simple-gui/src/main/java/com/example/spring/ui/MyAppFrame.java @@ -0,0 +1,96 @@ +package com.example.spring.ui; + +import java.awt.GridLayout; +import java.awt.HeadlessException; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import com.example.spring.logic.Maths; + + +public class MyAppFrame extends JFrame implements ActionListener { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private JButton button; + private JTextField textFiledA; + private JTextField textFiledB; + private JLabel answerPanel; + + private Maths maths; + + public void setMaths(Maths maths) { + this.maths = maths; + } + + public MyAppFrame() throws HeadlessException { + super("MyCalc"); + + setDefaultCloseOperation(EXIT_ON_CLOSE); + + textFiledA = new JTextField(); + textFiledA.setHorizontalAlignment(JTextField.RIGHT); + textFiledB = new JTextField(); + textFiledB.setHorizontalAlignment(JTextField.RIGHT); + button = new JButton("Add"); + answerPanel = new JLabel(); + + setLayout(new GridLayout(2, 2)); + + JPanel inputPanel = new JPanel(); + inputPanel.setLayout(new GridLayout(2, 2)); + + inputPanel.add(new JLabel("a:")); + inputPanel.add(textFiledA); + inputPanel.add(new JLabel("b:")); + inputPanel.add(textFiledB); + + add(inputPanel); + + + JPanel bottomSection = new JPanel(); + bottomSection.setLayout(new GridLayout(2, 1)); + + bottomSection.add(button); + bottomSection.add(answerPanel); + + add(bottomSection); + + + button.addActionListener(this); + + setSize(200, 300); + setVisible(true); + } + + @Override + public void actionPerformed(ActionEvent e) { + double a, b; + + try { + a = Double.parseDouble(textFiledA.getText()); + } catch (NumberFormatException nfe) { + answerPanel.setText("Value of \"a\" is invalid."); + return; + } + + try { + b = Double.parseDouble(textFiledB.getText()); + } catch (NumberFormatException nfe) { + answerPanel.setText("Value of \"b\" is invalid."); + return; + } + + double results = maths.add(a, b); + answerPanel.setText("Answer: " + results); + } +}
\ No newline at end of file diff --git a/spring-framework/05-simple-gui/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/05-simple-gui/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..4d7e736 --- /dev/null +++ b/spring-framework/05-simple-gui/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,13 @@ +<?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="mathsBean" class="com.example.spring.logic.MathsImpl"> + </bean> + + <bean class="com.example.spring.ui.MyAppFrame"> + <property name="maths" ref="mathsBean"></property> + </bean> + +</beans> diff --git a/spring-framework/07-bank-jdbc-ds-transaction/.gitignore b/spring-framework/07-bank-jdbc-ds-transaction/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/07-bank-jdbc-ds-transaction/pom.xml b/spring-framework/07-bank-jdbc-ds-transaction/pom.xml new file mode 100644 index 0000000..6a3307d --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/pom.xml @@ -0,0 +1,42 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>bank-jdbc-ds-transaction</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-jdbc</artifactId> + <version>${springVersion}</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-dbcp2</artifactId> + <version>${commonsDBCP2Version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + <version>${mariadbClientVersion}</version> + </dependency> + </dependencies> + +</project> diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/App.java b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..1060f2d --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/App.java @@ -0,0 +1,11 @@ +package com.example.spring; + +import com.example.spring.bank.BankApp; + +public class App { + public static void main(String[] args) { + // Actually, BankApp is the class with the main method. + // It should have been executed directly instead of this class. + BankApp.main(args); + } +} diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/Account.java b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/Account.java new file mode 100644 index 0000000..6222af8 --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/Account.java @@ -0,0 +1,21 @@ +package com.example.spring.bank; + +import java.math.BigDecimal; + +public class Account { + private int accountNumber; + private BigDecimal balance; + + public int getAccountNumber() { + return accountNumber; + } + public void setAccountNumber(int accountNumber) { + this.accountNumber = accountNumber; + } + public BigDecimal getBalance() { + return balance; + } + public void setBalance(BigDecimal balance) { + this.balance = balance; + } +} diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/AccountManager.java b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/AccountManager.java new file mode 100644 index 0000000..f299d60 --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/AccountManager.java @@ -0,0 +1,21 @@ +package com.example.spring.bank; + +import java.math.BigDecimal; + +public interface AccountManager { + + public Account create(); + + public Account find(int accountNumber); + + public Account deposit(int accountNumber, BigDecimal amount); + public Account withdraw(int accountNumber, BigDecimal amount); + + public void delete(int accountNumber); + + /** Returns the first account */ + public Account transfer(int accountNumber1, int accountNumber2, BigDecimal amount); + + public void chargeForLowBalance(BigDecimal minimumBalance, BigDecimal amount); + +} diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/AccountManagerImpl.java b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/AccountManagerImpl.java new file mode 100644 index 0000000..39dc63e --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/AccountManagerImpl.java @@ -0,0 +1,73 @@ +package com.example.spring.bank; + +import java.math.BigDecimal; +import java.util.Iterator; +import java.util.List; + +import com.example.spring.bank.dao.AccountDAO; + +public class AccountManagerImpl implements AccountManager { + + private AccountDAO accountDAO; + + public void setAccountDAO(AccountDAO accountDAO) { + this.accountDAO = accountDAO; + } + + @Override + public void chargeForLowBalance(BigDecimal minimumBalance, BigDecimal amount) { + List<Account> accounts = accountDAO.findAccountsWithLowBalance(minimumBalance); + for (Iterator<Account> iterator = accounts.iterator(); iterator.hasNext();) { + Account account = (Account) iterator.next(); + // Check if the balance will go beyond 0. If yes, set the balance to 0 + account.setBalance(account.getBalance().subtract(amount)); + accountDAO.update(account); + } + } + + @Override + public Account create() { + return accountDAO.createAccount(); + } + + @Override + public Account find(int accountNumber) { + return accountDAO.getAccount(accountNumber); + } + + @Override + public void delete(int accountNumber) { + accountDAO.delete(accountNumber); + } + + @Override + public Account deposit(int accountNumber, BigDecimal amount) { + Account account = accountDAO.getAccount(accountNumber); + account.setBalance(account.getBalance().add(amount)); + accountDAO.update(account); + + return account; + } + + @Override + public Account withdraw(int accountNumber, BigDecimal amount) { + Account account = accountDAO.getAccount(accountNumber); + account.setBalance(account.getBalance().subtract(amount)); + accountDAO.update(account); + + return account; + } + + @Override + public Account transfer(int accountNumber1, int accountNumber2, BigDecimal amount) { + Account account1 = accountDAO.getAccount(accountNumber1); + account1.setBalance(account1.getBalance().subtract(amount)); + accountDAO.update(account1); + + Account account2 = accountDAO.getAccount(accountNumber2); + account2.setBalance(account2.getBalance().add(amount)); + accountDAO.update(account2); + + return account1; + } +}
\ No newline at end of file diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/BankApp.java b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/BankApp.java new file mode 100644 index 0000000..26b6eaf --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/BankApp.java @@ -0,0 +1,65 @@ +package com.example.spring.bank; + +import java.math.BigDecimal; + +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class BankApp { + + /** + * @param args + */ + public static void main(String[] args) { + + AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"classpath:META-INF/spring/applicationContext.xml"}); + + // Register a shutdown hook with the JVM runtime, closing this context on JVM shutdown unless it has already been closed at that time. + // Delegates to doClose() for the actual closing procedure. + // This will trigger the destroy-method of the DataSource in our application (for example, in case of unexpected JVM shutdown). + ctx.registerShutdownHook(); + + AccountManager am = ctx.getBean("accountManager", AccountManager.class); + + // Create an account + System.out.println("Creating a new account..."); + Account account = am.create(); + + System.out.println("Account number: " + account.getAccountNumber()); + System.out.println("Balance: " + account.getBalance()); + + // Deposit some amount + System.out.println("Depositing 200.0..."); + account = am.deposit(account.getAccountNumber(), new BigDecimal("200.0")); + System.out.println("New balance: " + account.getBalance()); + + +// am.chargeForLowBalance(150, 10); + + System.out.println("Withdrawing 50.0..."); + account = am.withdraw(account.getAccountNumber(), new BigDecimal("50.0")); + System.out.println("New balance: " + account.getBalance()); + + // Create another account + Account account2 = am.create(); + // Try transfer + System.out.println("Trying transfer, 1st account balance: " + account.getBalance()); + account = am.transfer(account.getAccountNumber(), account2.getAccountNumber(), new BigDecimal("10.00")); + System.out.println("After transfer, 1st account balance: " + account.getBalance()); + + + System.out.println("Trying transfer to possibly non-existing account, 1st account balance: " + account.getBalance()); + try { + account = am.transfer(account.getAccountNumber(), 5000, new BigDecimal("10.00")); + } catch (Exception e) { + System.err.println("An error occurred!"); + e.printStackTrace(); + } + + account = am.find(account.getAccountNumber()); + System.out.println("After transfer, 1st account balance: " + account.getBalance()); + + ctx.close(); + } + +} diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/dao/AccountDAO.java b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/dao/AccountDAO.java new file mode 100644 index 0000000..735aed2 --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/dao/AccountDAO.java @@ -0,0 +1,15 @@ +package com.example.spring.bank.dao; + +import java.math.BigDecimal; +import java.util.List; + +import com.example.spring.bank.Account; + +public interface AccountDAO { + public Account createAccount(); + public Account getAccount(int accountNumber); + public void update(Account account); + public void delete(int accountNumber); + public List<Account> findAllAccounts(); + public List<Account> findAccountsWithLowBalance(BigDecimal lessThanAmount); +} diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/dao/jdbc/JDBCAccountDAO.java b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/dao/jdbc/JDBCAccountDAO.java new file mode 100644 index 0000000..d285a89 --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/dao/jdbc/JDBCAccountDAO.java @@ -0,0 +1,94 @@ +package com.example.spring.bank.dao.jdbc; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import javax.sql.DataSource; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.PreparedStatementCreator; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; + +import com.example.spring.bank.Account; +import com.example.spring.bank.dao.AccountDAO; + +public class JDBCAccountDAO implements AccountDAO { + + private JdbcTemplate jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + + @Override + public Account createAccount() { +// Connection con = dataSource.getConnection(); +// PreparedStatement stmt = con.prepareStatement("...", autoGeneratedKeys); +// stmt.execute(); +// con.close(); + + + final String INSERT_SQL = "insert into account (balance) values(0)"; + + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update( + new PreparedStatementCreator() { + public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { + PreparedStatement ps = + connection.prepareStatement(INSERT_SQL, new String[] {"account_number"}); + // ps.setString(1, name); + return ps; + } + }, keyHolder); + + Account account = new Account(); + // keyHolder.getKey() now contains the generated key + account.setAccountNumber(keyHolder.getKey().intValue()); + account.setBalance(new BigDecimal("0.0")); + + return account; + } + + @Override + public void delete(int accountNumber) { + jdbcTemplate.update("delete from account where account_number = ?", Integer.valueOf(accountNumber)); + } + + @Override + public List<Account> findAccountsWithLowBalance(BigDecimal lessThanAmount) { + return this.jdbcTemplate.query( "select * from account where balance < ?", new Object[] {lessThanAmount.doubleValue()}, new AccountMapper()); + } + + @Override + public List<Account> findAllAccounts() { + return this.jdbcTemplate.query( "select * from account", new AccountMapper()); + } + + @Override + public Account getAccount(int accountNumber) { + return this.jdbcTemplate.queryForObject( "select * from account where account_number = ?", new Object[] {accountNumber}, new AccountMapper()); + } + + @Override + public void update(Account account) { + this.jdbcTemplate.update("update account set balance = ? where account_number = ?", account.getBalance(), account.getAccountNumber()); + } + + + private static final class AccountMapper implements RowMapper<Account> { + + public Account mapRow(ResultSet rs, int rowNum) throws SQLException { + Account account = new Account(); + account.setAccountNumber(rs.getInt("account_number")); + account.setBalance(rs.getBigDecimal("balance")); + return account; + } + } +}
\ No newline at end of file diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/tx/TxAccountManager.java b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/tx/TxAccountManager.java new file mode 100644 index 0000000..a5b310d --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/java/com/example/spring/bank/tx/TxAccountManager.java @@ -0,0 +1,109 @@ +package com.example.spring.bank.tx; + +import java.math.BigDecimal; + +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; + +import com.example.spring.bank.Account; +import com.example.spring.bank.AccountManager; + +/** + * This class decorates a given AccountManager by adding transaction boundaries. + * + * @author kamal + * + */ +public class TxAccountManager implements AccountManager { + + private AccountManager accountManager; + + public void setAccountManager(AccountManager accountManager) { + this.accountManager = accountManager; + } + + private TransactionTemplate txTemplate; + + public void setTxManager(DataSourceTransactionManager txManager) { + txTemplate = new TransactionTemplate(txManager); + } + + @Override + public Account create() { + return txTemplate.execute(new TransactionCallback<Account>() { + @Override + public Account doInTransaction(TransactionStatus arg0) { + return accountManager.create(); + } + }); + } + + @Override + public Account find(int accountNumber) { + return accountManager.find(accountNumber); + } + + @Override + public Account deposit(int accountNumber, BigDecimal amount) { + return txTemplate.execute(new TransactionCallback<Account>() { + + @Override + public Account doInTransaction(TransactionStatus arg0) { + return accountManager.deposit(accountNumber, amount); + } + }); + } + + @Override + public Account withdraw(int accountNumber, BigDecimal amount) { + return txTemplate.execute(new TransactionCallback<Account>() { + + @Override + public Account doInTransaction(TransactionStatus arg0) { + return accountManager.withdraw(accountNumber, amount); + } + }); + } + + @Override + public void delete(int accountNumber) { + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus arg0) { + accountManager.delete(accountNumber); + } + }); + } + + @Override + public void chargeForLowBalance(BigDecimal minimumBalance, BigDecimal amount) { + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus arg0) { + accountManager.chargeForLowBalance(minimumBalance, amount); + } + }); + } + + @Override + public Account transfer(int accountNumber1, int accountNumber2, BigDecimal amount) { + return txTemplate.execute(new TransactionCallback<Account>() { + + @Override + public Account doInTransaction(TransactionStatus status) { + try { + return accountManager.transfer(accountNumber1, accountNumber2, amount); + } catch (Exception e) { + // Some exception occurred. + status.setRollbackOnly(); + throw e; + } + } + }); + } +} diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/07-bank-jdbc-ds-transaction/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..f57f28b --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:jdbc="http://www.springframework.org/schema/jdbc" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/jdbc + http://www.springframework.org/schema/jdbc/spring-jdbc.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:property-placeholder location="classpath:META-INF/spring/jdbc.properties"/> + + <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" > + <property name="driverClassName" value="${jdbc.driverClassName}"/> + <property name="url" value="${jdbc.url}"/> + <property name="username" value="${jdbc.username}"/> + <property name="password" value="${jdbc.password}"/> + </bean> + + <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> + <property name="dataSource" ref="dataSource"/> + </bean> + + <bean id="accountDAO" class="com.example.spring.bank.dao.jdbc.JDBCAccountDAO" > + <property name="dataSource" ref="dataSource"/> + </bean> + + <bean id="accountManagerWithNoTransactionSupport" class="com.example.spring.bank.AccountManagerImpl"> + <property name="accountDAO" ref="accountDAO"/> + </bean> + + <bean id="accountManager" class="com.example.spring.bank.tx.TxAccountManager"> + <property name="accountManager" ref="accountManagerWithNoTransactionSupport"/> + <property name="txManager" ref="txManager"/> + </bean> + +</beans>
\ No newline at end of file diff --git a/spring-framework/07-bank-jdbc-ds-transaction/src/main/resources/META-INF/spring/jdbc.properties b/spring-framework/07-bank-jdbc-ds-transaction/src/main/resources/META-INF/spring/jdbc.properties new file mode 100644 index 0000000..83220af --- /dev/null +++ b/spring-framework/07-bank-jdbc-ds-transaction/src/main/resources/META-INF/spring/jdbc.properties @@ -0,0 +1,9 @@ +jdbc.driverClassName=com.mysql.cj.jdbc.Driver +#jdbc.url=jdbc:mysql://localhost/bankdb?useSSL=false +#jdbc.url=jdbc:mysql://localhost/bankdb?useLegacyDatetimeCode=false&serverTimezone=UTC +jdbc.url=jdbc:mysql://localhost/bankdb?serverTimezone=Asia/Colombo +jdbc.username=bankdbuser +jdbc.password=abc123 + +#jdbc.driverClassName=org.postgresql.Driver +#jdbc.url=jdbc:postgresql://localhost/bank diff --git a/spring-framework/07-user-jdbc-ds-transaction/.gitignore b/spring-framework/07-user-jdbc-ds-transaction/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/07-user-jdbc-ds-transaction/misc/mysql-schema.sql b/spring-framework/07-user-jdbc-ds-transaction/misc/mysql-schema.sql new file mode 100644 index 0000000..5f7e263 --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/misc/mysql-schema.sql @@ -0,0 +1,7 @@ +CREATE TABLE user_account ( + uid int(11) primary key NOT NULL AUTO_INCREMENT, + username varchar(20) not null unique, + full_name text, + password char(32), + active boolean +) Engine=InnoDB; diff --git a/spring-framework/07-user-jdbc-ds-transaction/pom.xml b/spring-framework/07-user-jdbc-ds-transaction/pom.xml new file mode 100644 index 0000000..e2a1d1d --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/pom.xml @@ -0,0 +1,42 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>user-jdbc-ds-transaction</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-jdbc</artifactId> + <version>${springVersion}</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-dbcp2</artifactId> + <version>${commonsDBCP2Version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + <version>${mariadbClientVersion}</version> + </dependency> + </dependencies> + +</project> diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/FinancialPlannerApp.java b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/FinancialPlannerApp.java new file mode 100644 index 0000000..24b4675 --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/FinancialPlannerApp.java @@ -0,0 +1,45 @@ +package com.example.fp; + +import java.util.List; + +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class FinancialPlannerApp { + + /** + * @param args + */ + public static void main(String[] args) { + + AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"classpath:META-INF/spring/applicationContext.xml"}); + + // Register a shutdown hook with the JVM runtime, closing this context on JVM shutdown unless it has already been closed at that time. + // Delegates to doClose() for the actual closing procedure. + // This will trigger the destroy-method of the DataSource in our application (for example, in case of unexpected JVM shutdown). + ctx.registerShutdownHook(); + + UserManager userManager = ctx.getBean("userManager", UserManager.class); + + // Create an account + System.out.println("Creating users..."); + + userManager.create(new User("Kamal", "Kamal Wickramanayake", "abc123", true)); + userManager.create(new User("Rajith", "Rajith Virajana", "abc123", true)); + userManager.create(new User("Uththama", "Uththama Yapa", "abc123", true)); + + List<User> users = userManager.findAll(); + + for (User user : users) { + System.out.println(user); + } + + User newUser = new User("Kamal2", "Kamal Wickramanayake", "abc123", true); + System.out.println(newUser); + userManager.create(newUser); + System.out.println(newUser); + + ctx.close(); + } + +} diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/User.java b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/User.java new file mode 100644 index 0000000..d940b63 --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/User.java @@ -0,0 +1,115 @@ +package com.example.fp; + +public class User { + private Integer uid; + private String username; + private String fullName; + private String password; + private boolean active; + + public User() { + super(); + } + + public User(String username, String fullName, String password, boolean active) { + super(); + this.username = username; + this.fullName = fullName; + this.password = password; + this.active = active; + } + + + public User(Integer uid, String username, String fullName, String password, boolean active) { + super(); + this.uid = uid; + this.username = username; + this.fullName = fullName; + this.password = password; + this.active = active; + } + + public Integer getUid() { + return uid; + } + public void setUid(Integer uid) { + this.uid = uid; + } + + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String getFullName() { + return fullName; + } + public void setFullName(String fullName) { + this.fullName = fullName; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + public boolean isActive() { + return active; + } + public void setActive(boolean active) { + this.active = active; + } + + @Override + public String toString() { + return "User [uid=" + uid + ", username=" + username + ", fullName=" + fullName + ", active=" + active + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (active ? 1231 : 1237); + result = prime * result + ((fullName == null) ? 0 : fullName.hashCode()); + result = prime * result + ((password == null) ? 0 : password.hashCode()); + result = prime * result + uid; + result = prime * result + ((username == null) ? 0 : username.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (active != other.active) + return false; + if (fullName == null) { + if (other.fullName != null) + return false; + } else if (!fullName.equals(other.fullName)) + return false; + if (password == null) { + if (other.password != null) + return false; + } else if (!password.equals(other.password)) + return false; + if (uid != other.uid) + return false; + if (username == null) { + if (other.username != null) + return false; + } else if (!username.equals(other.username)) + return false; + return true; + } + + + + +} diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/UserManager.java b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/UserManager.java new file mode 100644 index 0000000..2412617 --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/UserManager.java @@ -0,0 +1,17 @@ +package com.example.fp; + +import java.util.List; + +public interface UserManager { + + public void create(User user); + + public User find(int uid); + public List<User> findAll(); + + public void delete(int uid); + + public void update(User user); + + public void setPassword(int uid, String plainTextPassword); +} diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/UserManagerImpl.java b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/UserManagerImpl.java new file mode 100644 index 0000000..ad2a58d --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/UserManagerImpl.java @@ -0,0 +1,78 @@ +package com.example.fp; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +import com.example.fp.dao.UserDAO; + +public class UserManagerImpl implements UserManager { + + private UserDAO userDAO; + + public void setUserDAO(UserDAO userDAO) { + this.userDAO = userDAO; + } + + @Override + public void create(User user) { + user.setPassword(calculatePasswordHash(user.getPassword())); + userDAO.create(user); + } + + @Override + public User find(int uid) { + return userDAO.find(uid); + } + + @Override + public List<User> findAll() { + return userDAO.findAll(); + } + + @Override + public void delete(int uid) { + userDAO.delete(uid); + } + + @Override + public void update(User user) { + userDAO.update(user); + } + + @Override + public void setPassword(int uid, String plainTextPassword) { + User user = userDAO.find(uid); + + user.setPassword(calculatePasswordHash(plainTextPassword)); + + userDAO.update(user); + } + + public static String calculatePasswordHash(String plainText) { + + try { + // Static getInstance method is called with hashing MD5 + MessageDigest md = MessageDigest.getInstance("MD5"); + + // digest() method is called to calculate message digest + // of an input digest() return array of byte + byte[] messageDigest = md.digest(plainText.getBytes()); + + // Convert byte array into signum representation + BigInteger no = new BigInteger(1, messageDigest); + + // Convert message digest into hex value + String hashtext = no.toString(16); + while (hashtext.length() < 32) { + hashtext = "0" + hashtext; + } + + return hashtext; + } catch (NoSuchAlgorithmException e) { + // For specifying wrong message digest algorithms + throw new RuntimeException(e); + } + } +}
\ No newline at end of file diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/dao/UserDAO.java b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/dao/UserDAO.java new file mode 100644 index 0000000..b0215b1 --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/dao/UserDAO.java @@ -0,0 +1,14 @@ +package com.example.fp.dao; + +import java.util.List; + +import com.example.fp.User; + +public interface UserDAO { + public void create(User user); + public User find(int uid); + public User find(String username); + public void delete(int uid); + public List<User> findAll(); + public void update(User user); +} diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/dao/jdbc/JDBCUserDAO.java b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/dao/jdbc/JDBCUserDAO.java new file mode 100644 index 0000000..80d77af --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/dao/jdbc/JDBCUserDAO.java @@ -0,0 +1,94 @@ +package com.example.fp.dao.jdbc; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import javax.sql.DataSource; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.PreparedStatementCreator; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; + +import com.example.fp.User; +import com.example.fp.dao.UserDAO; + +public class JDBCUserDAO implements UserDAO { + + private JdbcTemplate jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + + @Override + public void create(User user) { + + final String INSERT_SQL = "insert into user_account (username, full_name, password, active) values(?, ?, ?, ?)"; + + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update( + new PreparedStatementCreator() { + public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { + PreparedStatement ps = + connection.prepareStatement(INSERT_SQL, new String[] {"uid"}); + ps.setString(1, user.getUsername()); + ps.setString(2, user.getFullName()); + ps.setString(3, user.getPassword()); + ps.setInt(4, user.isActive() ? 1 : 0); + return ps; + } + }, keyHolder); + + // keyHolder.getKey() now contains the generated key + user.setUid(keyHolder.getKey().intValue()); + } + + @Override + public void delete(int uid) { + jdbcTemplate.update("delete from user_account where uid = ?", Integer.valueOf(uid)); + } + + @Override + public List<User> findAll() { + return this.jdbcTemplate.query( "select * from user_account", new UserMapper()); + } + + + @Override + public User find(int uid) { + return this.jdbcTemplate.queryForObject( "select * from user_account where uid = ?", new Object[] {Integer.valueOf(uid)}, new UserMapper()); + } + + + @Override + public User find(String username) { + return this.jdbcTemplate.queryForObject( "select * from user_account where username = ?", new Object[] {username}, new UserMapper()); + } + + + @Override + public void update(User user) { + this.jdbcTemplate.update("update user_account set username = ?, full_name = ?, password = ?, active = ? where uid = ?", + user.getUsername(), user.getFullName(), user.getPassword(), user.isActive() ? 1 : 0, user.getUid()); + } + + + private static final class UserMapper implements RowMapper<User> { + + public User mapRow(ResultSet rs, int rowNum) throws SQLException { + User user = new User(); + user.setUid(rs.getInt("uid")); + user.setUsername(rs.getString("username")); + user.setFullName(rs.getString("full_name")); + user.setPassword(rs.getString("password")); + user.setActive(rs.getBoolean("active")); + return user; + } + } +}
\ No newline at end of file diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/tx/TxUserManager.java b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/tx/TxUserManager.java new file mode 100644 index 0000000..4bb6d05 --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/fp/tx/TxUserManager.java @@ -0,0 +1,88 @@ +package com.example.fp.tx; + +import java.util.List; + +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; + +import com.example.fp.User; +import com.example.fp.UserManager; + +/** + * This class decorates a given AccountManager by adding transaction boundaries. + * + * @author kamal + * + */ +public class TxUserManager implements UserManager { + + private UserManager userManager; + + public void setUserManager(UserManager userManager) { + this.userManager = userManager; + } + + private TransactionTemplate txTemplate; + + public void setTxManager(DataSourceTransactionManager txManager) { + txTemplate = new TransactionTemplate(txManager); + } + + + @Override + public User find(int uid) { + return userManager.find(uid); + } + + + @Override + public void delete(int uid) { + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus arg0) { + userManager.delete(uid); + } + }); + } + + @Override + public void create(User user) { + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus arg0) { + userManager.create(user); + } + }); + } + + @Override + public List<User> findAll() { + return userManager.findAll(); + } + + @Override + public void update(User user) { + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus arg0) { + userManager.update(user); + } + }); + } + + @Override + public void setPassword(int uid, String plainTextPassword) { + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus arg0) { + userManager.setPassword(uid, plainTextPassword); + } + }); + } +} diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/spring/App.java b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..2fd9e86 --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/java/com/example/spring/App.java @@ -0,0 +1,11 @@ +package com.example.spring; + +import com.example.fp.FinancialPlannerApp; + +public class App { + public static void main(String[] args) { + // Actually, BankApp is the class with the main method. + // It should have been executed directly instead of this class. + FinancialPlannerApp.main(args); + } +} diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/07-user-jdbc-ds-transaction/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..9b85cd3 --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:jdbc="http://www.springframework.org/schema/jdbc" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/jdbc + http://www.springframework.org/schema/jdbc/spring-jdbc.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:property-placeholder location="classpath:META-INF/spring/jdbc.properties"/> + + <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" > + <property name="driverClassName" value="${jdbc.driverClassName}"/> + <property name="url" value="${jdbc.url}"/> + <property name="username" value="${jdbc.username}"/> + <property name="password" value="${jdbc.password}"/> + </bean> + + <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> + <property name="dataSource" ref="dataSource"/> + </bean> + + <bean id="userDAO" class="com.example.fp.dao.jdbc.JDBCUserDAO" > + <property name="dataSource" ref="dataSource"/> + </bean> + + <bean id="userManagerWithNoTransactionSupport" class="com.example.fp.UserManagerImpl"> + <property name="userDAO" ref="userDAO"/> + </bean> + + <bean id="userManager" class="com.example.fp.tx.TxUserManager"> + <property name="userManager" ref="userManagerWithNoTransactionSupport"/> + <property name="txManager" ref="txManager"/> + </bean> + +</beans>
\ No newline at end of file diff --git a/spring-framework/07-user-jdbc-ds-transaction/src/main/resources/META-INF/spring/jdbc.properties b/spring-framework/07-user-jdbc-ds-transaction/src/main/resources/META-INF/spring/jdbc.properties new file mode 100644 index 0000000..83220af --- /dev/null +++ b/spring-framework/07-user-jdbc-ds-transaction/src/main/resources/META-INF/spring/jdbc.properties @@ -0,0 +1,9 @@ +jdbc.driverClassName=com.mysql.cj.jdbc.Driver +#jdbc.url=jdbc:mysql://localhost/bankdb?useSSL=false +#jdbc.url=jdbc:mysql://localhost/bankdb?useLegacyDatetimeCode=false&serverTimezone=UTC +jdbc.url=jdbc:mysql://localhost/bankdb?serverTimezone=Asia/Colombo +jdbc.username=bankdbuser +jdbc.password=abc123 + +#jdbc.driverClassName=org.postgresql.Driver +#jdbc.url=jdbc:postgresql://localhost/bank diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/.gitignore b/spring-framework/08-bank-jdbc-servlet-webapp/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/misc/mysql-schema.sql b/spring-framework/08-bank-jdbc-servlet-webapp/misc/mysql-schema.sql new file mode 100644 index 0000000..167aa55 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/misc/mysql-schema.sql @@ -0,0 +1,4 @@ +CREATE TABLE account ( + account_number int(11) primary key NOT NULL AUTO_INCREMENT, + balance float DEFAULT NULL +) Engine=InnoDB; diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/misc/postgressql-schema.sql b/spring-framework/08-bank-jdbc-servlet-webapp/misc/postgressql-schema.sql new file mode 100644 index 0000000..6ed17fa --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/misc/postgressql-schema.sql @@ -0,0 +1,10 @@ +CREATE TABLE account ( + account_number int(11) primary key NOT NULL, + balance float DEFAULT NULL +); + +CREATE SEQUENCE account_account_number_seq; + +ALTER TABLE account + ALTER COLUMN account_number + SET DEFAULT NEXTVAL('account_account_number_seq');
\ No newline at end of file diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/pom.xml b/spring-framework/08-bank-jdbc-servlet-webapp/pom.xml new file mode 100644 index 0000000..cbd9d29 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/pom.xml @@ -0,0 +1,43 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config-webapps</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config-webapps</relativePath> + </parent> + + <artifactId>bank-jdbc-servlet-webapp</artifactId> + <packaging>war</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-jdbc</artifactId> + <version>${springVersion}</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-dbcp2</artifactId> + <version>${commonsDBCP2Version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + <version>${mariadbClientVersion}</version> + </dependency> + + </dependencies> + +</project> diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/Account.java b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/Account.java new file mode 100644 index 0000000..6222af8 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/Account.java @@ -0,0 +1,21 @@ +package com.example.spring.bank; + +import java.math.BigDecimal; + +public class Account { + private int accountNumber; + private BigDecimal balance; + + public int getAccountNumber() { + return accountNumber; + } + public void setAccountNumber(int accountNumber) { + this.accountNumber = accountNumber; + } + public BigDecimal getBalance() { + return balance; + } + public void setBalance(BigDecimal balance) { + this.balance = balance; + } +} diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/AccountManager.java b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/AccountManager.java new file mode 100644 index 0000000..f299d60 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/AccountManager.java @@ -0,0 +1,21 @@ +package com.example.spring.bank; + +import java.math.BigDecimal; + +public interface AccountManager { + + public Account create(); + + public Account find(int accountNumber); + + public Account deposit(int accountNumber, BigDecimal amount); + public Account withdraw(int accountNumber, BigDecimal amount); + + public void delete(int accountNumber); + + /** Returns the first account */ + public Account transfer(int accountNumber1, int accountNumber2, BigDecimal amount); + + public void chargeForLowBalance(BigDecimal minimumBalance, BigDecimal amount); + +} diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/AccountManagerImpl.java b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/AccountManagerImpl.java new file mode 100644 index 0000000..39dc63e --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/AccountManagerImpl.java @@ -0,0 +1,73 @@ +package com.example.spring.bank; + +import java.math.BigDecimal; +import java.util.Iterator; +import java.util.List; + +import com.example.spring.bank.dao.AccountDAO; + +public class AccountManagerImpl implements AccountManager { + + private AccountDAO accountDAO; + + public void setAccountDAO(AccountDAO accountDAO) { + this.accountDAO = accountDAO; + } + + @Override + public void chargeForLowBalance(BigDecimal minimumBalance, BigDecimal amount) { + List<Account> accounts = accountDAO.findAccountsWithLowBalance(minimumBalance); + for (Iterator<Account> iterator = accounts.iterator(); iterator.hasNext();) { + Account account = (Account) iterator.next(); + // Check if the balance will go beyond 0. If yes, set the balance to 0 + account.setBalance(account.getBalance().subtract(amount)); + accountDAO.update(account); + } + } + + @Override + public Account create() { + return accountDAO.createAccount(); + } + + @Override + public Account find(int accountNumber) { + return accountDAO.getAccount(accountNumber); + } + + @Override + public void delete(int accountNumber) { + accountDAO.delete(accountNumber); + } + + @Override + public Account deposit(int accountNumber, BigDecimal amount) { + Account account = accountDAO.getAccount(accountNumber); + account.setBalance(account.getBalance().add(amount)); + accountDAO.update(account); + + return account; + } + + @Override + public Account withdraw(int accountNumber, BigDecimal amount) { + Account account = accountDAO.getAccount(accountNumber); + account.setBalance(account.getBalance().subtract(amount)); + accountDAO.update(account); + + return account; + } + + @Override + public Account transfer(int accountNumber1, int accountNumber2, BigDecimal amount) { + Account account1 = accountDAO.getAccount(accountNumber1); + account1.setBalance(account1.getBalance().subtract(amount)); + accountDAO.update(account1); + + Account account2 = accountDAO.getAccount(accountNumber2); + account2.setBalance(account2.getBalance().add(amount)); + accountDAO.update(account2); + + return account1; + } +}
\ No newline at end of file diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/dao/AccountDAO.java b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/dao/AccountDAO.java new file mode 100644 index 0000000..735aed2 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/dao/AccountDAO.java @@ -0,0 +1,15 @@ +package com.example.spring.bank.dao; + +import java.math.BigDecimal; +import java.util.List; + +import com.example.spring.bank.Account; + +public interface AccountDAO { + public Account createAccount(); + public Account getAccount(int accountNumber); + public void update(Account account); + public void delete(int accountNumber); + public List<Account> findAllAccounts(); + public List<Account> findAccountsWithLowBalance(BigDecimal lessThanAmount); +} diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/dao/jdbc/JDBCAccountDAO.java b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/dao/jdbc/JDBCAccountDAO.java new file mode 100644 index 0000000..d285a89 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/dao/jdbc/JDBCAccountDAO.java @@ -0,0 +1,94 @@ +package com.example.spring.bank.dao.jdbc; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import javax.sql.DataSource; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.PreparedStatementCreator; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; + +import com.example.spring.bank.Account; +import com.example.spring.bank.dao.AccountDAO; + +public class JDBCAccountDAO implements AccountDAO { + + private JdbcTemplate jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + + @Override + public Account createAccount() { +// Connection con = dataSource.getConnection(); +// PreparedStatement stmt = con.prepareStatement("...", autoGeneratedKeys); +// stmt.execute(); +// con.close(); + + + final String INSERT_SQL = "insert into account (balance) values(0)"; + + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update( + new PreparedStatementCreator() { + public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { + PreparedStatement ps = + connection.prepareStatement(INSERT_SQL, new String[] {"account_number"}); + // ps.setString(1, name); + return ps; + } + }, keyHolder); + + Account account = new Account(); + // keyHolder.getKey() now contains the generated key + account.setAccountNumber(keyHolder.getKey().intValue()); + account.setBalance(new BigDecimal("0.0")); + + return account; + } + + @Override + public void delete(int accountNumber) { + jdbcTemplate.update("delete from account where account_number = ?", Integer.valueOf(accountNumber)); + } + + @Override + public List<Account> findAccountsWithLowBalance(BigDecimal lessThanAmount) { + return this.jdbcTemplate.query( "select * from account where balance < ?", new Object[] {lessThanAmount.doubleValue()}, new AccountMapper()); + } + + @Override + public List<Account> findAllAccounts() { + return this.jdbcTemplate.query( "select * from account", new AccountMapper()); + } + + @Override + public Account getAccount(int accountNumber) { + return this.jdbcTemplate.queryForObject( "select * from account where account_number = ?", new Object[] {accountNumber}, new AccountMapper()); + } + + @Override + public void update(Account account) { + this.jdbcTemplate.update("update account set balance = ? where account_number = ?", account.getBalance(), account.getAccountNumber()); + } + + + private static final class AccountMapper implements RowMapper<Account> { + + public Account mapRow(ResultSet rs, int rowNum) throws SQLException { + Account account = new Account(); + account.setAccountNumber(rs.getInt("account_number")); + account.setBalance(rs.getBigDecimal("balance")); + return account; + } + } +}
\ No newline at end of file diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/tx/TxAccountManager.java b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/tx/TxAccountManager.java new file mode 100644 index 0000000..a5b310d --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/tx/TxAccountManager.java @@ -0,0 +1,109 @@ +package com.example.spring.bank.tx; + +import java.math.BigDecimal; + +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; + +import com.example.spring.bank.Account; +import com.example.spring.bank.AccountManager; + +/** + * This class decorates a given AccountManager by adding transaction boundaries. + * + * @author kamal + * + */ +public class TxAccountManager implements AccountManager { + + private AccountManager accountManager; + + public void setAccountManager(AccountManager accountManager) { + this.accountManager = accountManager; + } + + private TransactionTemplate txTemplate; + + public void setTxManager(DataSourceTransactionManager txManager) { + txTemplate = new TransactionTemplate(txManager); + } + + @Override + public Account create() { + return txTemplate.execute(new TransactionCallback<Account>() { + @Override + public Account doInTransaction(TransactionStatus arg0) { + return accountManager.create(); + } + }); + } + + @Override + public Account find(int accountNumber) { + return accountManager.find(accountNumber); + } + + @Override + public Account deposit(int accountNumber, BigDecimal amount) { + return txTemplate.execute(new TransactionCallback<Account>() { + + @Override + public Account doInTransaction(TransactionStatus arg0) { + return accountManager.deposit(accountNumber, amount); + } + }); + } + + @Override + public Account withdraw(int accountNumber, BigDecimal amount) { + return txTemplate.execute(new TransactionCallback<Account>() { + + @Override + public Account doInTransaction(TransactionStatus arg0) { + return accountManager.withdraw(accountNumber, amount); + } + }); + } + + @Override + public void delete(int accountNumber) { + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus arg0) { + accountManager.delete(accountNumber); + } + }); + } + + @Override + public void chargeForLowBalance(BigDecimal minimumBalance, BigDecimal amount) { + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus arg0) { + accountManager.chargeForLowBalance(minimumBalance, amount); + } + }); + } + + @Override + public Account transfer(int accountNumber1, int accountNumber2, BigDecimal amount) { + return txTemplate.execute(new TransactionCallback<Account>() { + + @Override + public Account doInTransaction(TransactionStatus status) { + try { + return accountManager.transfer(accountNumber1, accountNumber2, amount); + } catch (Exception e) { + // Some exception occurred. + status.setRollbackOnly(); + throw e; + } + } + }); + } +} diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/web/BankGateway.java b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/web/BankGateway.java new file mode 100644 index 0000000..e7908d5 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/java/com/example/spring/bank/web/BankGateway.java @@ -0,0 +1,59 @@ +package com.example.spring.bank.web; + +import java.io.IOException; +import java.math.BigDecimal; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import com.example.spring.bank.AccountManager; + +/** + * Servlet implementation class BankGateway + */ +public class BankGateway extends HttpServlet { + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public BankGateway() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + getServletContext().getRequestDispatcher("/deposit.jsp").forward(request, response); + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); + AccountManager am = ctx.getBean("accountManager", AccountManager.class); + + int accountNumber = Integer.parseInt(request.getParameter("accountNumber")); + BigDecimal amount = new BigDecimal(request.getParameter("amount")); + + // How to use a session scoped bean (Example only) +// DepositForm form = (DepositForm) ctx.getBean("depositForm"); +// form.setAccountNumber(accountNumber); +// form.setAmount(amount); + // End of example + + + am.deposit(accountNumber, amount); + + // We can dispatch to a success page if we prefer! + getServletContext().getRequestDispatcher("/deposit.jsp").forward(request, response); + } + +} diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/spring/applicationContext.xml b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/spring/applicationContext.xml new file mode 100644 index 0000000..138f5d2 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/spring/applicationContext.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:jdbc="http://www.springframework.org/schema/jdbc" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/jdbc + http://www.springframework.org/schema/jdbc/spring-jdbc.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:property-placeholder location="/WEB-INF/spring/jdbc.properties"/> + + <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" > + <property name="driverClassName" value="${jdbc.driverClassName}"/> + <property name="url" value="${jdbc.url}"/> + <property name="username" value="${jdbc.username}"/> + <property name="password" value="${jdbc.password}"/> + </bean> + + <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> + <property name="dataSource" ref="dataSource"/> + </bean> + + <bean id="accountDAO" class="com.example.spring.bank.dao.jdbc.JDBCAccountDAO" > + <property name="dataSource" ref="dataSource"/> + </bean> + + <bean id="accountManagerWithNoTransactionSupport" class="com.example.spring.bank.AccountManagerImpl"> + <property name="accountDAO" ref="accountDAO"/> + </bean> + + <bean id="accountManager" class="com.example.spring.bank.tx.TxAccountManager"> + <property name="accountManager" ref="accountManagerWithNoTransactionSupport"/> + <property name="txManager" ref="txManager"/> + </bean> + +</beans>
\ No newline at end of file diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/spring/jdbc.properties b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/spring/jdbc.properties new file mode 100644 index 0000000..09ab3ec --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/spring/jdbc.properties @@ -0,0 +1,7 @@ +jdbc.driverClassName=com.mysql.cj.jdbc.Driver +jdbc.url=jdbc:mysql://localhost/bankdb?useSSL=false +jdbc.username=bankdbuser +jdbc.password=abc123 + +#jdbc.driverClassName=org.postgresql.Driver +#jdbc.url=jdbc:postgresql://localhost/bank diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/web.xml b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..0fa6cae --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> + <display-name>BankBasicWeb</display-name> + <welcome-file-list> + <welcome-file>index.html</welcome-file> + <welcome-file>index.htm</welcome-file> + <welcome-file>index.jsp</welcome-file> + <welcome-file>default.html</welcome-file> + <welcome-file>default.htm</welcome-file> + <welcome-file>default.jsp</welcome-file> + </welcome-file-list> + <servlet> + <description></description> + <display-name>BankGateway</display-name> + <servlet-name>BankGateway</servlet-name> + <servlet-class>com.example.spring.bank.web.BankGateway</servlet-class> + </servlet> + <servlet-mapping> + <servlet-name>BankGateway</servlet-name> + <url-pattern>/BankGateway</url-pattern> + </servlet-mapping> + <listener> + <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> + </listener> + <context-param> + <param-name>contextConfigLocation</param-name> + <param-value>/WEB-INF/spring/*Context.xml</param-value> + </context-param> +</web-app>
\ No newline at end of file diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/deposit.jsp b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/deposit.jsp new file mode 100644 index 0000000..ede3415 --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/deposit.jsp @@ -0,0 +1,21 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Deposit Money</title> +<link rel="stylesheet" type="text/css" href="style/style.css"> +</head> + +<body> + + <form method="post" action="BankGateway"> + Account No: <input type="text" name="accountNumber" /> + Amount: <input type="text" name="amount" /> + <input type="submit" name="submit" value="Deposit" /> + </form> + +</body> +</html>
\ No newline at end of file diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/index.jsp b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/index.jsp new file mode 100644 index 0000000..324aa4f --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/index.jsp @@ -0,0 +1,14 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Deposit Money</title> +</head> +<body> + +<a href="deposit.jsp">Deposit</a> + +</body> +</html>
\ No newline at end of file diff --git a/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/style/style.css b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/style/style.css new file mode 100644 index 0000000..38e09ca --- /dev/null +++ b/spring-framework/08-bank-jdbc-servlet-webapp/src/main/webapp/style/style.css @@ -0,0 +1,4 @@ +input { + display:block; + margin-bottom: 0.5em; +}
\ No newline at end of file diff --git a/spring-framework/20-aop-xml/.gitignore b/spring-framework/20-aop-xml/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/20-aop-xml/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/20-aop-xml/pom.xml b/spring-framework/20-aop-xml/pom.xml new file mode 100644 index 0000000..8b723ef --- /dev/null +++ b/spring-framework/20-aop-xml/pom.xml @@ -0,0 +1,30 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>aop-xml</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <version>${springVersion}</version> + </dependency> + + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjweaver</artifactId> + <version>${aspectjVersion}</version> + </dependency> + + </dependencies> +</project> diff --git a/spring-framework/20-aop-xml/src/main/java/com/example/spring/App.java b/spring-framework/20-aop-xml/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..13a782c --- /dev/null +++ b/spring-framework/20-aop-xml/src/main/java/com/example/spring/App.java @@ -0,0 +1,11 @@ +package com.example.spring; + +import com.example.spring.aop.BankApp; + +public class App { + public static void main(String[] args) { + // Actually, BankApp is the class with the main method. + // It should have been executed directly instead of this class. + BankApp.main(args); + } +} diff --git a/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/Account.java b/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/Account.java new file mode 100644 index 0000000..f2d0e84 --- /dev/null +++ b/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/Account.java @@ -0,0 +1,38 @@ +package com.example.spring.aop; + +public class Account { + private int accNo; + private double balance; + + public void withdraw(double amount) { + if (balance >= amount) { + balance -= amount; + } + } + + public void deposit(double amount) { +// System.out.println("Account.deposit()"); + balance += amount; + } + + + public void printDetails() { + System.out.println("Balance of " + accNo + " : " + balance); + } + + public int getAccNo() { + return accNo; + } + + public void setAccNo(int accNo) { + this.accNo = accNo; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } +} diff --git a/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/BankApp.java b/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/BankApp.java new file mode 100644 index 0000000..760b139 --- /dev/null +++ b/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/BankApp.java @@ -0,0 +1,29 @@ +package com.example.spring.aop; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class BankApp { + + /** + * @param args + */ + public static void main(String[] args) { + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + Account acc = ctx.getBean("account", Account.class); + + acc.printDetails(); // 250 + acc.withdraw(10); + acc.printDetails(); // 240 + acc.deposit(20); + acc.printDetails(); // 260 + + System.out.println("An exception should occur here if attempted to withdraw a large amount."); + acc.withdraw(1200); // Uncommented, this should throw an exception + acc.printDetails(); // 260 + + ctx.close(); + } + +} diff --git a/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/security/AccessChecker.java b/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/security/AccessChecker.java new file mode 100644 index 0000000..97384c3 --- /dev/null +++ b/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/security/AccessChecker.java @@ -0,0 +1,15 @@ +package com.example.spring.aop.security; + +public class AccessChecker { + + public void checkDepositPermission() { + System.out.println("Aspect is checking deposit permission..."); + } + + public void checkWithdrawPermission(double amount) { + System.out.println("Aspect is checking withdraw permission for " + amount); + if (amount > 1000.0) { + throw new AccessException("Withdrawing more than 1000.0 is not allowed."); + } + } +} diff --git a/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/security/AccessException.java b/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/security/AccessException.java new file mode 100644 index 0000000..0e1b60c --- /dev/null +++ b/spring-framework/20-aop-xml/src/main/java/com/example/spring/aop/security/AccessException.java @@ -0,0 +1,30 @@ +package com.example.spring.aop.security; + +public class AccessException extends RuntimeException { + + + /** + * + */ + private static final long serialVersionUID = -6529989268011261235L; + + public AccessException() { + // TODO Auto-generated constructor stub + } + + public AccessException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + public AccessException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + public AccessException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + +} diff --git a/spring-framework/20-aop-xml/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/20-aop-xml/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..ecf08e4 --- /dev/null +++ b/spring-framework/20-aop-xml/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:aop="http://www.springframework.org/schema/aop" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> + + <bean id="account" class="com.example.spring.aop.Account"> + <property name="accNo" value="1000"></property> + <property name="balance" value="250.00"></property> + </bean> + + <!-- Here is a bean representing the security aspect --> + + <bean id="accessChecker" class="com.example.spring.aop.security.AccessChecker" /> + + <aop:config> + <aop:aspect id="securityAspect" ref="accessChecker"> + + <aop:pointcut id="deposit" + expression="execution(public * com.example.spring.aop.Account.deposit(..))" /> + <aop:before pointcut-ref="deposit" + method="checkDepositPermission" /> + + <aop:pointcut id="withdraw" + expression="execution(public * com.example.spring.aop.Account.withdraw(..)) and args(amount)" /> + <aop:before pointcut-ref="withdraw" + method="checkWithdrawPermission(double)" /> + + </aop:aspect> + + </aop:config> + +</beans>
\ No newline at end of file diff --git a/spring-framework/21-aop-xml-args/.gitignore b/spring-framework/21-aop-xml-args/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/21-aop-xml-args/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/21-aop-xml-args/pom.xml b/spring-framework/21-aop-xml-args/pom.xml new file mode 100644 index 0000000..f62bc57 --- /dev/null +++ b/spring-framework/21-aop-xml-args/pom.xml @@ -0,0 +1,30 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>aop-xml-args</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <version>${springVersion}</version> + </dependency> + + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjweaver</artifactId> + <version>${aspectjVersion}</version> + </dependency> + + </dependencies> +</project> diff --git a/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/App.java b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..13a782c --- /dev/null +++ b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/App.java @@ -0,0 +1,11 @@ +package com.example.spring; + +import com.example.spring.aop.BankApp; + +public class App { + public static void main(String[] args) { + // Actually, BankApp is the class with the main method. + // It should have been executed directly instead of this class. + BankApp.main(args); + } +} diff --git a/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/Account.java b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/Account.java new file mode 100644 index 0000000..f2d0e84 --- /dev/null +++ b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/Account.java @@ -0,0 +1,38 @@ +package com.example.spring.aop; + +public class Account { + private int accNo; + private double balance; + + public void withdraw(double amount) { + if (balance >= amount) { + balance -= amount; + } + } + + public void deposit(double amount) { +// System.out.println("Account.deposit()"); + balance += amount; + } + + + public void printDetails() { + System.out.println("Balance of " + accNo + " : " + balance); + } + + public int getAccNo() { + return accNo; + } + + public void setAccNo(int accNo) { + this.accNo = accNo; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } +} diff --git a/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/BankApp.java b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/BankApp.java new file mode 100644 index 0000000..2473692 --- /dev/null +++ b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/BankApp.java @@ -0,0 +1,29 @@ +package com.example.spring.aop; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class BankApp { + + /** + * @param args + */ + public static void main(String[] args) { + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + Account acc = ctx.getBean("account", Account.class); + + acc.printDetails(); // 250 + acc.withdraw(10); + acc.printDetails(); // 240 + acc.deposit(20); + acc.printDetails(); // 260 + + System.out.println("An exception should occur here if attempted to withdraw a large amount."); +// acc.withdraw(1200); // Uncommented, this should throw an exception + acc.printDetails(); // 260 + + ctx.close(); + } + +} diff --git a/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/aoplogger/Logger.java b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/aoplogger/Logger.java new file mode 100644 index 0000000..89adc56 --- /dev/null +++ b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/aoplogger/Logger.java @@ -0,0 +1,14 @@ +package com.example.spring.aop.aoplogger; + +import org.aspectj.lang.JoinPoint; + +public class Logger { + + public void beforMethodExecuted(JoinPoint joinPoint) { + System.out.println("AOP Logger (BEFORE): " + joinPoint.getSignature()); + } + + public void afterMethodExecuted(JoinPoint joinPoint) { + System.out.println("AOP Logger (AFTER): " + joinPoint.getSignature()); + } +} diff --git a/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessChecker.java b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessChecker.java new file mode 100644 index 0000000..8167f08 --- /dev/null +++ b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessChecker.java @@ -0,0 +1,16 @@ +package com.example.spring.aop.security; + +public class AccessChecker { + + public void checkDepositPermission() { + System.out.println("Aspect is checking deposit permission..."); + } + + + public void checkWithdrawPermission(double amount) { + System.out.println("Aspect is checking withdraw permission for " + amount); + if (amount > 1000.0) { + throw new AccessException("Withdrawing more than 1000.0 is not allowed."); + } + } +} diff --git a/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessChecker2.java b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessChecker2.java new file mode 100644 index 0000000..4174f04 --- /dev/null +++ b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessChecker2.java @@ -0,0 +1,16 @@ +package com.example.spring.aop.security; + +import org.aspectj.lang.JoinPoint; + +public class AccessChecker2 { + + public void checkDepositPermission(JoinPoint joinPoint) { + Object[] args = joinPoint.getArgs(); + System.out.println("Deposit amount: " + args[0]); + } + + public void checkWithdrawPermission(JoinPoint joinPoint) { + Object[] args = joinPoint.getArgs(); + System.out.println("Withdraw amount: " + args[0]); + } +} diff --git a/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessException.java b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessException.java new file mode 100644 index 0000000..0e1b60c --- /dev/null +++ b/spring-framework/21-aop-xml-args/src/main/java/com/example/spring/aop/security/AccessException.java @@ -0,0 +1,30 @@ +package com.example.spring.aop.security; + +public class AccessException extends RuntimeException { + + + /** + * + */ + private static final long serialVersionUID = -6529989268011261235L; + + public AccessException() { + // TODO Auto-generated constructor stub + } + + public AccessException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + public AccessException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + public AccessException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + +} diff --git a/spring-framework/21-aop-xml-args/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/21-aop-xml-args/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..70d0c07 --- /dev/null +++ b/spring-framework/21-aop-xml-args/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:aop="http://www.springframework.org/schema/aop" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> + + <bean id="account" class="com.example.spring.aop.Account"> + <property name="accNo" value="1000"></property> + <property name="balance" value="250.00"></property> + </bean> + + <!-- Here is a bean representing the security aspect --> + <bean id="accessChecker" + class="com.example.spring.aop.security.AccessChecker2" /> + + <!-- This aspect can print the method signatures when methods are executed + - before, and after --> + <bean id="aopLogger" + class="com.example.spring.aop.aoplogger.Logger" /> + + <aop:config> + <aop:aspect id="securityAspect" ref="accessChecker"> + + <aop:pointcut id="deposit" + expression="execution(public * com.example.spring.aop.Account.deposit(..))" /> + <aop:before pointcut-ref="deposit" + method="checkDepositPermission" /> + + <aop:pointcut id="withdraw" + expression="execution(public * com.example.spring.aop.Account.withdraw(..))" /> + <aop:before pointcut-ref="withdraw" + method="checkWithdrawPermission" /> + + </aop:aspect> + + <aop:aspect id="loggerAspect" ref="aopLogger"> + + <aop:pointcut id="bankPackageMethod" + expression="execution(public * com.example.spring.aop.**.*(..))" /> + <aop:before pointcut-ref="bankPackageMethod" + method="beforMethodExecuted" /> + <aop:after pointcut-ref="bankPackageMethod" + method="afterMethodExecuted" /> + + </aop:aspect> + + </aop:config> + + +</beans>
\ No newline at end of file diff --git a/spring-framework/22-aop-xml-around/.gitignore b/spring-framework/22-aop-xml-around/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/22-aop-xml-around/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/22-aop-xml-around/pom.xml b/spring-framework/22-aop-xml-around/pom.xml new file mode 100644 index 0000000..b9da4a8 --- /dev/null +++ b/spring-framework/22-aop-xml-around/pom.xml @@ -0,0 +1,30 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>aop-xml-around</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <version>${springVersion}</version> + </dependency> + + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjweaver</artifactId> + <version>${aspectjVersion}</version> + </dependency> + + </dependencies> +</project> diff --git a/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/App.java b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..13a782c --- /dev/null +++ b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/App.java @@ -0,0 +1,11 @@ +package com.example.spring; + +import com.example.spring.aop.BankApp; + +public class App { + public static void main(String[] args) { + // Actually, BankApp is the class with the main method. + // It should have been executed directly instead of this class. + BankApp.main(args); + } +} diff --git a/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/Account.java b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/Account.java new file mode 100644 index 0000000..f2d0e84 --- /dev/null +++ b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/Account.java @@ -0,0 +1,38 @@ +package com.example.spring.aop; + +public class Account { + private int accNo; + private double balance; + + public void withdraw(double amount) { + if (balance >= amount) { + balance -= amount; + } + } + + public void deposit(double amount) { +// System.out.println("Account.deposit()"); + balance += amount; + } + + + public void printDetails() { + System.out.println("Balance of " + accNo + " : " + balance); + } + + public int getAccNo() { + return accNo; + } + + public void setAccNo(int accNo) { + this.accNo = accNo; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } +} diff --git a/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/BankApp.java b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/BankApp.java new file mode 100644 index 0000000..2473692 --- /dev/null +++ b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/BankApp.java @@ -0,0 +1,29 @@ +package com.example.spring.aop; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class BankApp { + + /** + * @param args + */ + public static void main(String[] args) { + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + Account acc = ctx.getBean("account", Account.class); + + acc.printDetails(); // 250 + acc.withdraw(10); + acc.printDetails(); // 240 + acc.deposit(20); + acc.printDetails(); // 260 + + System.out.println("An exception should occur here if attempted to withdraw a large amount."); +// acc.withdraw(1200); // Uncommented, this should throw an exception + acc.printDetails(); // 260 + + ctx.close(); + } + +} diff --git a/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/aoplogger/Logger.java b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/aoplogger/Logger.java new file mode 100644 index 0000000..4ca8621 --- /dev/null +++ b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/aoplogger/Logger.java @@ -0,0 +1,26 @@ +package com.example.spring.aop.aoplogger; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; + +public class Logger { + + public void beforMethodExecuted(JoinPoint joinPoint) { + System.out.println("AOP Logger (BEFORE): " + joinPoint.getSignature()); + } + + public void afterMethodExecuted(JoinPoint joinPoint) { + System.out.println("AOP Logger (AFTER): " + joinPoint.getSignature()); + } + + public Object methodExecutionMonitor(ProceedingJoinPoint pjp) throws Throwable { + + long startTime = System.nanoTime(); + Object retVal = pjp.proceed(); + long endTime = System.nanoTime(); + + System.out.println("Method execution time (ns): " + pjp.getSignature() + " " + (endTime - startTime)); + + return retVal; + } +} diff --git a/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessChecker.java b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessChecker.java new file mode 100644 index 0000000..8167f08 --- /dev/null +++ b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessChecker.java @@ -0,0 +1,16 @@ +package com.example.spring.aop.security; + +public class AccessChecker { + + public void checkDepositPermission() { + System.out.println("Aspect is checking deposit permission..."); + } + + + public void checkWithdrawPermission(double amount) { + System.out.println("Aspect is checking withdraw permission for " + amount); + if (amount > 1000.0) { + throw new AccessException("Withdrawing more than 1000.0 is not allowed."); + } + } +} diff --git a/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessChecker2.java b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessChecker2.java new file mode 100644 index 0000000..4174f04 --- /dev/null +++ b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessChecker2.java @@ -0,0 +1,16 @@ +package com.example.spring.aop.security; + +import org.aspectj.lang.JoinPoint; + +public class AccessChecker2 { + + public void checkDepositPermission(JoinPoint joinPoint) { + Object[] args = joinPoint.getArgs(); + System.out.println("Deposit amount: " + args[0]); + } + + public void checkWithdrawPermission(JoinPoint joinPoint) { + Object[] args = joinPoint.getArgs(); + System.out.println("Withdraw amount: " + args[0]); + } +} diff --git a/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessException.java b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessException.java new file mode 100644 index 0000000..0e1b60c --- /dev/null +++ b/spring-framework/22-aop-xml-around/src/main/java/com/example/spring/aop/security/AccessException.java @@ -0,0 +1,30 @@ +package com.example.spring.aop.security; + +public class AccessException extends RuntimeException { + + + /** + * + */ + private static final long serialVersionUID = -6529989268011261235L; + + public AccessException() { + // TODO Auto-generated constructor stub + } + + public AccessException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + public AccessException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + public AccessException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + +} diff --git a/spring-framework/22-aop-xml-around/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/22-aop-xml-around/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..b6126cf --- /dev/null +++ b/spring-framework/22-aop-xml-around/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:aop="http://www.springframework.org/schema/aop" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> + + <bean id="account" class="com.example.spring.aop.Account"> + <property name="accNo" value="1000"></property> + <property name="balance" value="250.00"></property> + </bean> + + <!-- Here is a bean representing the security aspect --> + <bean id="accessChecker" + class="com.example.spring.aop.security.AccessChecker2" /> + + <!-- This aspect can print the method signatures when methods are executed + - before, and after --> + <bean id="aopLogger" + class="com.example.spring.aop.aoplogger.Logger" /> + + <aop:config> + <!-- <aop:aspect id="securityAspect" ref="accessChecker"> --> + + <!-- <aop:pointcut id="deposit" --> + <!-- expression="execution(public * com.example.spring.aop.Account.deposit(..))" + /> --> + <!-- <aop:before pointcut-ref="deposit" --> + <!-- method="checkDepositPermission" /> --> + + <!-- <aop:pointcut id="withdraw" --> + <!-- expression="execution(public * com.example.spring.aop.Account.withdraw(..))" + /> --> + <!-- <aop:before pointcut-ref="withdraw" --> + <!-- method="checkWithdrawPermission" /> --> + + <!-- </aop:aspect> --> + + <!-- <aop:aspect id="loggerAspect" ref="aopLogger"> --> + + <!-- <aop:pointcut id="bankPackageMethod" --> + <!-- expression="execution(public * com.example.spring.aop.**.*(..))" /> --> + <!-- <aop:before pointcut-ref="bankPackageMethod" --> + <!-- method="beforMethodExecuted" /> --> + <!-- <aop:after pointcut-ref="bankPackageMethod" --> + <!-- method="afterMethodExecuted" /> --> + + <!-- </aop:aspect> --> + + <aop:aspect id="loggerAspect" ref="aopLogger"> + <aop:pointcut id="allMethods" + expression="execution(public * com.example.spring.aop.**.*(..))" /> + <aop:around pointcut-ref="allMethods" + method="methodExecutionMonitor" /> + </aop:aspect> + </aop:config> + + +</beans>
\ No newline at end of file diff --git a/spring-framework/23-aop-aspectj-annotations/.gitignore b/spring-framework/23-aop-aspectj-annotations/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/23-aop-aspectj-annotations/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/23-aop-aspectj-annotations/pom.xml b/spring-framework/23-aop-aspectj-annotations/pom.xml new file mode 100644 index 0000000..29cd955 --- /dev/null +++ b/spring-framework/23-aop-aspectj-annotations/pom.xml @@ -0,0 +1,30 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>aop-aspectj-annotations</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <version>${springVersion}</version> + </dependency> + + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjweaver</artifactId> + <version>${aspectjVersion}</version> + </dependency> + + </dependencies> +</project> diff --git a/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/App.java b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..13a782c --- /dev/null +++ b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/App.java @@ -0,0 +1,11 @@ +package com.example.spring; + +import com.example.spring.aop.BankApp; + +public class App { + public static void main(String[] args) { + // Actually, BankApp is the class with the main method. + // It should have been executed directly instead of this class. + BankApp.main(args); + } +} diff --git a/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/Account.java b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/Account.java new file mode 100644 index 0000000..f2d0e84 --- /dev/null +++ b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/Account.java @@ -0,0 +1,38 @@ +package com.example.spring.aop; + +public class Account { + private int accNo; + private double balance; + + public void withdraw(double amount) { + if (balance >= amount) { + balance -= amount; + } + } + + public void deposit(double amount) { +// System.out.println("Account.deposit()"); + balance += amount; + } + + + public void printDetails() { + System.out.println("Balance of " + accNo + " : " + balance); + } + + public int getAccNo() { + return accNo; + } + + public void setAccNo(int accNo) { + this.accNo = accNo; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } +} diff --git a/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/BankApp.java b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/BankApp.java new file mode 100644 index 0000000..6ad43cf --- /dev/null +++ b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/BankApp.java @@ -0,0 +1,29 @@ +package com.example.spring.aop; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class BankApp { + + /** + * @param args + */ + public static void main(String[] args) { + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + Account acc = ctx.getBean("account", Account.class); + + acc.printDetails(); // 250 + acc.withdraw(10); + acc.printDetails(); // 240 + acc.deposit(20); + acc.printDetails(); // 260 + +// System.out.println("An exception should occur here if attempted to withdraw a large amount."); +// acc.withdraw(1200); // Uncommented, this should throw an exception +// acc.printDetails(); // 260 + + ctx.close(); + } + +} diff --git a/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/security/AccessChecker.java b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/security/AccessChecker.java new file mode 100644 index 0000000..cd721f7 --- /dev/null +++ b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/security/AccessChecker.java @@ -0,0 +1,32 @@ +package com.example.spring.aop.security; + +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; + +@Aspect +public class AccessChecker { + + /* + * In-place pointcut expressions are used here (i.e. the pointcut + * expression is just declared with the advice directly rather than + * elsewhere). + */ + @Before("execution(public * com.example.spring.aop.Account.deposit(..))") + public void checkDepositPermission() { + System.out.println("Aspect is checking deposit permission..."); + } + + @After("execution(public * com.example.spring.aop.Account.deposit(..))") + public void checkDepositPermissionAfterDemo() { + System.out.println("checkDepositPermissionAfterDemo()"); + } + + @Before("execution(public * com.example.spring.aop.Account.withdraw(..)) && args(amount)") + public void checkWithdrawPermission(double amount) { + System.out.println("Aspect is checking withdraw permission for " + amount); + if (amount > 1000.0) { + throw new AccessException("Withdrawing more than 1000.0 is not allowed."); + } + } +} diff --git a/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/security/AccessException.java b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/security/AccessException.java new file mode 100644 index 0000000..0e1b60c --- /dev/null +++ b/spring-framework/23-aop-aspectj-annotations/src/main/java/com/example/spring/aop/security/AccessException.java @@ -0,0 +1,30 @@ +package com.example.spring.aop.security; + +public class AccessException extends RuntimeException { + + + /** + * + */ + private static final long serialVersionUID = -6529989268011261235L; + + public AccessException() { + // TODO Auto-generated constructor stub + } + + public AccessException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + public AccessException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + public AccessException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + +} diff --git a/spring-framework/23-aop-aspectj-annotations/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/23-aop-aspectj-annotations/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..5eaa647 --- /dev/null +++ b/spring-framework/23-aop-aspectj-annotations/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:aop="http://www.springframework.org/schema/aop" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> + + <!-- Enabled annotation based AOP --> + <aop:aspectj-autoproxy/> + + <!-- Aspect classes should be defined as beans --> + <bean id="accessChecker" class="com.example.spring.aop.security.AccessChecker" /> + + <bean id="account" class="com.example.spring.aop.Account"> + <property name="accNo" value="1000"></property> + <property name="balance" value="250.00"></property> + </bean> + +</beans>
\ No newline at end of file diff --git a/spring-framework/24-aop-aspectj-annotations2/.gitignore b/spring-framework/24-aop-aspectj-annotations2/.gitignore new file mode 100644 index 0000000..ec4e05e --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/.gitignore @@ -0,0 +1,9 @@ +# Eclipse +bin +.settings +.metadata +.classpath +.project + +# Maven +target diff --git a/spring-framework/24-aop-aspectj-annotations2/pom.xml b/spring-framework/24-aop-aspectj-annotations2/pom.xml new file mode 100644 index 0000000..a109101 --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/pom.xml @@ -0,0 +1,30 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.example.spring</groupId> + <artifactId>base-config</artifactId> + <version>0.0.1-SNAPSHOT</version> + <relativePath>../00-config</relativePath> + </parent> + + <artifactId>aop-aspectj-annotations2</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <version>${springVersion}</version> + </dependency> + + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjweaver</artifactId> + <version>${aspectjVersion}</version> + </dependency> + + </dependencies> +</project> diff --git a/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/App.java b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/App.java new file mode 100644 index 0000000..13a782c --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/App.java @@ -0,0 +1,11 @@ +package com.example.spring; + +import com.example.spring.aop.BankApp; + +public class App { + public static void main(String[] args) { + // Actually, BankApp is the class with the main method. + // It should have been executed directly instead of this class. + BankApp.main(args); + } +} diff --git a/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/Account.java b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/Account.java new file mode 100644 index 0000000..f2d0e84 --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/Account.java @@ -0,0 +1,38 @@ +package com.example.spring.aop; + +public class Account { + private int accNo; + private double balance; + + public void withdraw(double amount) { + if (balance >= amount) { + balance -= amount; + } + } + + public void deposit(double amount) { +// System.out.println("Account.deposit()"); + balance += amount; + } + + + public void printDetails() { + System.out.println("Balance of " + accNo + " : " + balance); + } + + public int getAccNo() { + return accNo; + } + + public void setAccNo(int accNo) { + this.accNo = accNo; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } +} diff --git a/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/BankApp.java b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/BankApp.java new file mode 100644 index 0000000..6ad43cf --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/BankApp.java @@ -0,0 +1,29 @@ +package com.example.spring.aop; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class BankApp { + + /** + * @param args + */ + public static void main(String[] args) { + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { + "classpath:META-INF/spring/applicationContext.xml",}); + + Account acc = ctx.getBean("account", Account.class); + + acc.printDetails(); // 250 + acc.withdraw(10); + acc.printDetails(); // 240 + acc.deposit(20); + acc.printDetails(); // 260 + +// System.out.println("An exception should occur here if attempted to withdraw a large amount."); +// acc.withdraw(1200); // Uncommented, this should throw an exception +// acc.printDetails(); // 260 + + ctx.close(); + } + +} diff --git a/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/AccessChecker.java b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/AccessChecker.java new file mode 100644 index 0000000..dff17bc --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/AccessChecker.java @@ -0,0 +1,50 @@ +package com.example.spring.aop.security; + +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; + +@Aspect +public class AccessChecker { + + /* + * In-place pointcut expressions are used here (i.e. the pointcut + * expression is just declared with the advice directly rather than + * elsewhere). + */ +// @Before("execution(public * com.example.spring.aop.Account.deposit(..))") +// public void checkDepositPermission() { +// System.out.println("Aspect is checking deposit permission..."); +// } +// +// @After("execution(public * com.example.spring.aop.Account.deposit(..))") +// public void checkDepositPermissionAfterDemo() { +// System.out.println("checkDepositPermissionAfterDemo()"); +// } +// +// @Before("execution(public * com.example.spring.aop.Account.withdraw(..)) && args(amount)") +// public void checkWithdrawPermission(double amount) { +// System.out.println("Aspect is checking withdraw permission for " + amount); +// if (amount > 1000.0) { +// throw new AccessException("Withdrawing more than 1000.0 is not allowed."); +// } +// } + + + @Before("MyPointcuts.abc()") + public void checkDepositPermission() { + System.out.println("Aspect is checking deposit permission..."); + } + + @Before("MyPointcuts.checkWithAmount(amount)") + public void checkWithdrawPermission(double amount) { + System.out.println("Aspect is checking withdraw permission for " + amount); + if (amount > 1000.0) { + throw new AccessException("Withdrawing more than 1000.0 is not allowed."); + } + } + + @Before("MyPointcuts.depositAndWithdraw()") + public void depositAndWithdraw() { + System.out.println("depositAndWithdraw()"); + } +} diff --git a/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/AccessException.java b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/AccessException.java new file mode 100644 index 0000000..0e1b60c --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/AccessException.java @@ -0,0 +1,30 @@ +package com.example.spring.aop.security; + +public class AccessException extends RuntimeException { + + + /** + * + */ + private static final long serialVersionUID = -6529989268011261235L; + + public AccessException() { + // TODO Auto-generated constructor stub + } + + public AccessException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + public AccessException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + public AccessException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + +} diff --git a/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/MyPointcuts.java b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/MyPointcuts.java new file mode 100644 index 0000000..51f7104 --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/src/main/java/com/example/spring/aop/security/MyPointcuts.java @@ -0,0 +1,20 @@ +package com.example.spring.aop.security; + +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; + +@Aspect +public class MyPointcuts { + + /* + * Following are the pointcut declarations. Note that these can be defined in separate classes as well. + */ + @Pointcut("execution(public * com.example.spring.aop.Account.withdraw(..)) && args(amount)") // pointcut expression - a selector + public void checkWithAmount(double amount) {} // pointcut signature - the name for the pointcut + + @Pointcut("execution(public * com.example.spring.aop.Account.deposit(..))") // pointcut expression - a selector + public void abc() {} // pointcut signature - the name for the pointcut + + @Pointcut("execution(public * com.example.spring.aop.Account.withdraw(..)) || execution(public * com.example.spring.aop.Account.deposit(..))") + public void depositAndWithdraw() {} +} diff --git a/spring-framework/24-aop-aspectj-annotations2/src/main/resources/META-INF/spring/applicationContext.xml b/spring-framework/24-aop-aspectj-annotations2/src/main/resources/META-INF/spring/applicationContext.xml new file mode 100644 index 0000000..1da13a1 --- /dev/null +++ b/spring-framework/24-aop-aspectj-annotations2/src/main/resources/META-INF/spring/applicationContext.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:aop="http://www.springframework.org/schema/aop" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> + + <!-- Enabled annotation based AOP --> + <aop:aspectj-autoproxy/> + + <!-- This been describes pointcuts --> + <bean id="myPointcuts" class="com.example.spring.aop.security.MyPointcuts" /> + + <!-- This bean simply references pointcuts --> + <bean id="accessChecker" class="com.example.spring.aop.security.AccessChecker" /> + + + <bean id="account" class="com.example.spring.aop.Account"> + <property name="accNo" value="1000"></property> + <property name="balance" value="250.00"></property> + </bean> + +</beans>
\ No newline at end of file |
