├── .gitignore ├── LICENSE ├── README.md ├── circle.yml ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── yet │ │ └── spring │ │ └── core │ │ ├── App.java │ │ ├── aspects │ │ ├── ConsoleLoggerLimitAspect.java │ │ ├── LoggingAspect.java │ │ └── StatisticsAspect.java │ │ ├── beans │ │ ├── Client.java │ │ ├── Event.java │ │ └── EventType.java │ │ ├── loggers │ │ ├── AbstractLogger.java │ │ ├── CacheFileEventLogger.java │ │ ├── CombinedEventLogger.java │ │ ├── ConsoleEventLogger.java │ │ ├── DBLogger.java │ │ ├── EventLogger.java │ │ └── FileEventLogger.java │ │ └── util │ │ ├── AwareBean.java │ │ └── Monitor.java └── resources │ ├── aspects.xml │ ├── client.properties │ ├── db.properties │ ├── db.xml │ ├── loggers.xml │ └── spring.xml └── test ├── java └── com │ └── yet │ └── spring │ └── core │ ├── TestApp.java │ ├── TestContext.java │ ├── aspects │ ├── TestConsoleLoggerLimitAspect.java │ └── TestStatisticsAspect.java │ ├── beans │ └── TestEvent.java │ └── loggers │ ├── TestCacheFileEventLogger.java │ ├── TestCombinedEventLogger.java │ ├── TestConsoleEventLogger.java │ ├── TestDBLogger.java │ └── TestFileEventLogger.java └── resources └── db_for_test.properties /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .classpath 3 | .project 4 | /.settings 5 | /.c9 6 | .idea/ 7 | *.iml 8 | /derby.log 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Yuriy Tkach 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spring-basics-course-project 2 | Исходный код небольшого проекта, создание которого происходит во время выполнения практики в онлайн-курсе [Spring Framework - The Basics](https://www.youtube.com/playlist?list=PL6jg6AGdCNaWF-sUH2QDudBRXo54zuN1t) :movie_camera: 3 | 4 | Чтобы посмотреть файлы, относящиеся к определенному уроку, т.е. всё то, что было сделано в предыдущих уроках и на данном уроке, Вы можете сделать checkout тега **lesson#**, где **#** - это номер урока. Например: 5 | * `git clone git@github.com:yuriytkach/spring-basics-course-project.git` - клонируем себе репозиторий 6 | * `cd spring-basics-course-project` - переходим в папку проекта 7 | * `git checkout lesson3 -b branch_lesson3` - получаем файлы для третьего урока в отдельной branch с именем _branch_lesson3_ 8 | 9 | :us: 10 | 11 | Source code of the small project that is created during the online course [Spring Framework - The Basics](https://www.youtube.com/playlist?list=PL6jg6AGdCNaWF-sUH2QDudBRXo54zuN1t) :movie_camera: 12 | 13 | To view the files for specific lesson, i.e. everything that was done on previous lessons plus on this lesson, you can just checkout the tag **lesson#** where **#** - is the lesson number. For example: 14 | * `git clone git@github.com:yuriytkach/spring-basics-course-project.git` - cloning the repository 15 | * `cd spring-basics-course-project` - changing directory to project one 16 | * `git checkout lesson3 -b branch_lesson3` - getting files for third lesson in a separate branch with name _branch_lesson3_ 17 | 18 | 19 | ## Quick links 20 | 21 | |Item |Link | 22 | |:---------------------|:-----------------------------------------------------------------------------------------| 23 | |Continuous integration| [![CircleCI](https://circleci.com/gh/yuriytkach/spring-basics-course-project.svg?style=svg)](https://circleci.com/gh/yuriytkach/spring-basics-course-project) | 24 | |Code coverage | [![Coverage Status](https://coveralls.io/repos/github/yuriytkach/spring-basics-course-project/badge.svg?branch=master)](https://coveralls.io/github/yuriytkach/spring-basics-course-project?branch=master) | 25 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | test: 2 | override: 3 | - mvn -DrepoToken=${repoToken} -P circleci integration-test jacoco:report coveralls:report 4 | post: 5 | - mkdir -p $CIRCLE_TEST_REPORTS/junit/ 6 | - find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \; 7 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.yet.spring 5 | com.yet.spring.core 6 | 0.13-SNAPSHOT 7 | Spring Basics Course Project 8 | The project created throughout the course 'Spring Framework - The Basics' 9 | 10 | 11 | 3.2.13.RELEASE 12 | 4.12 13 | 2.2.12 14 | 2.4 15 | 16 | 1.8.9 17 | 18 | 10.13.1.1 19 | 20 | 1.8 21 | UTF-8 22 | 23 | 24 | 25 | 26 | circleci 27 | 28 | 29 | ${CIRCLE_ARTIFACTS} 30 | 31 | 32 | 33 | 34 | org.eluder.coveralls 35 | coveralls-maven-plugin 36 | 4.3.0 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.springframework 46 | spring-context 47 | ${spring.version} 48 | 49 | 50 | org.springframework 51 | spring-context-support 52 | ${spring.version} 53 | 54 | 55 | org.springframework 56 | spring-tx 57 | ${spring.version} 58 | 59 | 60 | org.springframework 61 | spring-jdbc 62 | ${spring.version} 63 | 64 | 65 | 66 | org.apache.derby 67 | derby 68 | ${derby.version} 69 | 70 | 71 | 72 | org.aspectj 73 | aspectjweaver 74 | ${aspectj.version} 75 | 76 | 77 | 78 | commons-io 79 | commons-io 80 | ${commons.io.version} 81 | 82 | 83 | 84 | junit 85 | junit 86 | ${junit.version} 87 | test 88 | 89 | 90 | 91 | org.mockito 92 | mockito-core 93 | ${mockito.version} 94 | test 95 | 96 | 97 | 98 | 99 | 100 | 101 | org.apache.maven.plugins 102 | maven-compiler-plugin 103 | 3.3 104 | 105 | ${java.version} 106 | ${java.version} 107 | ${java.version} 108 | ${project.build.sourceEncoding} 109 | true 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | org.jacoco 117 | jacoco-maven-plugin 118 | 0.7.9 119 | 120 | 121 | prepare-agent 122 | 123 | prepare-agent 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | https://github.com/yuriytkach/spring-basics-course-project 133 | Github 134 | 135 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/App.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.ConfigurableApplicationContext; 7 | import org.springframework.context.support.ClassPathXmlApplicationContext; 8 | 9 | import com.yet.spring.core.beans.Client; 10 | import com.yet.spring.core.beans.Event; 11 | import com.yet.spring.core.beans.EventType; 12 | import com.yet.spring.core.loggers.EventLogger; 13 | 14 | public class App { 15 | 16 | private Client client; 17 | 18 | private EventLogger defaultLogger; 19 | 20 | private Map loggers; 21 | 22 | private String startupMessage; 23 | 24 | public static void main(String[] args) { 25 | ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( 26 | "spring.xml", "loggers.xml", "aspects.xml", "db.xml"); 27 | App app = (App) ctx.getBean("app"); 28 | 29 | System.out.println(app.startupMessage); 30 | 31 | Client client = ctx.getBean(Client.class); 32 | System.out.println("Client says: " + client.getGreeting()); 33 | 34 | app.logEvents(ctx); 35 | 36 | ctx.close(); 37 | } 38 | 39 | public void logEvents(ApplicationContext ctx) { 40 | Event event = ctx.getBean(Event.class); 41 | logEvent(EventType.INFO, event, "Some event for 1"); 42 | 43 | event = ctx.getBean(Event.class); 44 | logEvent(EventType.INFO, event, "One more event for 1"); 45 | 46 | event = ctx.getBean(Event.class); 47 | logEvent(EventType.INFO, event, "And one more event for 1"); 48 | 49 | event = ctx.getBean(Event.class); 50 | logEvent(EventType.ERROR, event, "Some event for 2"); 51 | 52 | event = ctx.getBean(Event.class); 53 | logEvent(null, event, "Some event for 3"); 54 | } 55 | 56 | public App() {} 57 | 58 | public App(Client client, EventLogger eventLogger, Map loggers) { 59 | super(); 60 | this.client = client; 61 | this.defaultLogger = eventLogger; 62 | this.loggers = loggers; 63 | } 64 | 65 | private void logEvent(EventType eventType, Event event, String msg) { 66 | String message = msg.replaceAll(client.getId(), client.getFullName()); 67 | event.setMsg(message); 68 | 69 | EventLogger logger = loggers.get(eventType); 70 | if (logger == null) { 71 | logger = defaultLogger; 72 | } 73 | 74 | logger.logEvent(event); 75 | } 76 | 77 | public void setStartupMessage(String startupMessage) { 78 | this.startupMessage = startupMessage; 79 | } 80 | 81 | public EventLogger getDefaultLogger() { 82 | return defaultLogger; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/aspects/ConsoleLoggerLimitAspect.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.aspects; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | 5 | import com.yet.spring.core.beans.Event; 6 | import com.yet.spring.core.loggers.EventLogger; 7 | 8 | public class ConsoleLoggerLimitAspect { 9 | 10 | private final int maxCount; 11 | 12 | private final EventLogger otherLogger; 13 | 14 | private int currentCount = 0; 15 | 16 | public ConsoleLoggerLimitAspect(int maxCount, EventLogger otherLogger) { 17 | this.maxCount = maxCount; 18 | this.otherLogger = otherLogger; 19 | } 20 | 21 | public void aroundLogEvent(ProceedingJoinPoint jp, Event evt) throws Throwable { 22 | if (currentCount < maxCount) { 23 | System.out.println("ConsoleEventLogger max count is not reached. Continue..."); 24 | currentCount++; 25 | jp.proceed(new Object[] {evt}); 26 | } else { 27 | System.out.println("ConsoleEventLogger max count is reached. Logging to " + otherLogger.getName()); 28 | otherLogger.logEvent(evt); 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/aspects/LoggingAspect.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.aspects; 2 | 3 | import org.aspectj.lang.JoinPoint; 4 | import org.aspectj.lang.annotation.AfterReturning; 5 | import org.aspectj.lang.annotation.AfterThrowing; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Before; 8 | import org.aspectj.lang.annotation.Pointcut; 9 | 10 | @Aspect 11 | public class LoggingAspect { 12 | 13 | @Pointcut("execution(* *.logEvent(..))") 14 | private void allLogEventMethods() {} 15 | 16 | @Pointcut("allLogEventMethods() && within(*.*File*Logger)") 17 | private void logEventInsideFileLoggers() {} 18 | 19 | @Before("allLogEventMethods()") 20 | public void logBefore(JoinPoint joinPoint) { 21 | System.out.println("BEFORE: " + 22 | joinPoint.getTarget().getClass().getSimpleName() + " " + 23 | joinPoint.getSignature().getName()); 24 | } 25 | 26 | @AfterReturning(pointcut="allLogEventMethods()", 27 | returning="retVal") 28 | public void logAfter(Object retVal) { 29 | System.out.println("AFTER_RET: " + retVal); 30 | } 31 | 32 | @AfterThrowing(pointcut="allLogEventMethods()", 33 | throwing="ex") 34 | public void logAfterThrow(Throwable ex) { 35 | System.out.println("AFTER_THR: " + ex); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/aspects/StatisticsAspect.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.aspects; 2 | 3 | import java.util.Collections; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Map.Entry; 7 | 8 | import org.aspectj.lang.JoinPoint; 9 | import org.aspectj.lang.annotation.AfterReturning; 10 | import org.aspectj.lang.annotation.Aspect; 11 | import org.aspectj.lang.annotation.Pointcut; 12 | 13 | @Aspect 14 | public class StatisticsAspect { 15 | 16 | private Map, Integer> counter = new HashMap<>(); 17 | 18 | @Pointcut("execution(* *.logEvent(..))") 19 | private void allLogEventMethods() {} 20 | 21 | @AfterReturning("allLogEventMethods()") 22 | public void count(JoinPoint jp) { 23 | Class clazz = jp.getTarget().getClass(); 24 | if (!counter.containsKey(clazz)) { 25 | counter.put(clazz, 0); 26 | } 27 | counter.put(clazz, counter.get(clazz) + 1); 28 | } 29 | 30 | public Map, Integer> getCounter() { 31 | return Collections.unmodifiableMap(counter); 32 | } 33 | 34 | @AfterReturning("execution(* com.yet.spring.core.App.logEvents(..))") 35 | public void outputLoggingCounter() { 36 | System.out.println("Loggers statistics. Number of calls: "); 37 | for (Entry, Integer> entry : counter.entrySet()) { 38 | System.out.println(" " + entry.getKey().getSimpleName() + ": " + entry.getValue()); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/beans/Client.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.beans; 2 | 3 | public class Client { 4 | 5 | private String id; 6 | 7 | private String fullName; 8 | 9 | private String greeting; 10 | 11 | public Client(String id, String fullName) { 12 | super(); 13 | this.id = id; 14 | this.fullName = fullName; 15 | } 16 | 17 | public String getId() { 18 | return id; 19 | } 20 | 21 | public void setId(String id) { 22 | this.id = id; 23 | } 24 | 25 | public String getFullName() { 26 | return fullName; 27 | } 28 | 29 | public void setFullName(String fullName) { 30 | this.fullName = fullName; 31 | } 32 | 33 | public String getGreeting() { 34 | return greeting; 35 | } 36 | 37 | public void setGreeting(String greeting) { 38 | this.greeting = greeting; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/beans/Event.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.beans; 2 | 3 | import java.text.DateFormat; 4 | import java.time.LocalTime; 5 | import java.util.Date; 6 | import java.util.Objects; 7 | import java.util.concurrent.atomic.AtomicInteger; 8 | 9 | public class Event { 10 | 11 | private static final AtomicInteger AUTO_ID = new AtomicInteger(0); 12 | 13 | public static boolean isDay(int start, int end) { 14 | LocalTime time = LocalTime.now(); 15 | return time.getHour() > start && time.getHour() < end; 16 | } 17 | 18 | public static void initAutoId(int id) { 19 | AUTO_ID.set(id); 20 | } 21 | 22 | private int id; 23 | private String msg; 24 | private Date date; 25 | 26 | private DateFormat dateFormat; 27 | 28 | public Event(int id, Date date, String msg) { 29 | this.id = id; 30 | this.date = date; 31 | this.msg = msg; 32 | } 33 | 34 | public Event(Date date, DateFormat df) { 35 | this.id = AUTO_ID.getAndIncrement(); 36 | 37 | this.date = date; 38 | this.dateFormat = df; 39 | } 40 | 41 | public String getMsg() { 42 | return msg; 43 | } 44 | 45 | public void setMsg(String msg) { 46 | this.msg = msg; 47 | } 48 | 49 | public int getId() { 50 | return id; 51 | } 52 | 53 | public Date getDate() { 54 | return date; 55 | } 56 | 57 | public DateFormat getDateFormat() { 58 | return dateFormat; 59 | } 60 | 61 | public void setDateFormat(DateFormat dateFormat) { 62 | this.dateFormat = dateFormat; 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return "Event [id=" + id + ", msg=" + msg + ", date=" + dateFormat.format(date) + "]"; 68 | } 69 | 70 | @Override 71 | public int hashCode() { 72 | return Objects.hash(id); 73 | } 74 | 75 | @Override 76 | public boolean equals(Object obj) { 77 | if (this == obj) 78 | return true; 79 | if (obj == null) 80 | return false; 81 | if (getClass() != obj.getClass()) 82 | return false; 83 | Event other = (Event) obj; 84 | if (id != other.id) 85 | return false; 86 | return true; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/beans/EventType.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.beans; 2 | 3 | public enum EventType { 4 | 5 | INFO, 6 | ERROR; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/loggers/AbstractLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | public abstract class AbstractLogger implements EventLogger { 4 | 5 | private String name; 6 | 7 | @Override 8 | public String getName() { 9 | return name; 10 | } 11 | 12 | public void setName(String name) { 13 | this.name = name; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/loggers/CacheFileEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.yet.spring.core.beans.Event; 7 | 8 | public class CacheFileEventLogger extends FileEventLogger { 9 | 10 | private int cacheSize; 11 | private List cache; 12 | 13 | public CacheFileEventLogger(String filename, int cacheSize) { 14 | super(filename); 15 | this.cacheSize = cacheSize; 16 | this.cache = new ArrayList(cacheSize); 17 | } 18 | 19 | public void destroy() { 20 | if ( ! cache.isEmpty()) { 21 | writeEventsFromCache(); 22 | } 23 | } 24 | 25 | @Override 26 | public void logEvent(Event event) { 27 | cache.add(event); 28 | 29 | if (cache.size() == cacheSize) { 30 | writeEventsFromCache(); 31 | cache.clear(); 32 | } 33 | } 34 | 35 | private void writeEventsFromCache() { 36 | cache.stream().forEach(super::logEvent); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/loggers/CombinedEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | 6 | import com.yet.spring.core.beans.Event; 7 | 8 | public class CombinedEventLogger extends AbstractLogger { 9 | 10 | private final Collection loggers; 11 | 12 | public CombinedEventLogger(Collection loggers) { 13 | super(); 14 | this.loggers = loggers; 15 | } 16 | 17 | @Override 18 | public void logEvent(Event event) { 19 | for (EventLogger eventLogger : loggers) { 20 | eventLogger.logEvent(event); 21 | } 22 | } 23 | 24 | public Collection getLoggers() { 25 | return Collections.unmodifiableCollection(loggers); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/loggers/ConsoleEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import com.yet.spring.core.beans.Event; 4 | 5 | public class ConsoleEventLogger extends AbstractLogger { 6 | 7 | @Override 8 | public void logEvent(Event event) { 9 | System.out.println(event.toString()); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/loggers/DBLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import java.sql.Date; 4 | import java.sql.ResultSet; 5 | import java.sql.SQLException; 6 | import java.util.List; 7 | import java.util.stream.Collectors; 8 | 9 | import org.springframework.dao.DataAccessException; 10 | import org.springframework.jdbc.core.JdbcTemplate; 11 | import org.springframework.jdbc.core.RowMapper; 12 | 13 | import com.yet.spring.core.beans.Event; 14 | 15 | public class DBLogger extends AbstractLogger { 16 | 17 | private static final String SQL_ERROR_STATE_SCHEMA_EXISTS = "X0Y68"; 18 | private static final String SQL_ERROR_STATE_TABLE_EXISTS = "X0Y32"; 19 | 20 | private JdbcTemplate jdbcTemplate; 21 | private String schema; 22 | 23 | public DBLogger(JdbcTemplate jdbcTemplate, String schema) { 24 | this.jdbcTemplate = jdbcTemplate; 25 | this.schema = schema.toUpperCase(); 26 | } 27 | 28 | public void init() { 29 | createDBSchema(); 30 | createTableIfNotExists(); 31 | updateEventAutoId(); 32 | } 33 | 34 | public void destroy() { 35 | int totalEvents = getTotalEvents(); 36 | System.out.println("Total events in the DB: " + totalEvents); 37 | 38 | List allEvents = getAllEvents(); 39 | String allEventIds = allEvents.stream() 40 | .map(Event::getId) 41 | .map(String::valueOf) 42 | .collect(Collectors.joining(", ")); 43 | System.out.println("All DB Event ids: " + allEventIds); 44 | } 45 | 46 | private void createDBSchema() { 47 | try { 48 | jdbcTemplate.update("CREATE SCHEMA " + schema); 49 | } catch (DataAccessException e) { 50 | Throwable causeException = e.getCause(); 51 | if (causeException instanceof SQLException) { 52 | SQLException sqlException = (SQLException) causeException; 53 | if (sqlException.getSQLState().equals(SQL_ERROR_STATE_SCHEMA_EXISTS)) { 54 | System.out.println("Schema already exists"); 55 | } else { 56 | throw e; 57 | } 58 | } else { 59 | throw e; 60 | } 61 | } 62 | } 63 | 64 | private void createTableIfNotExists() { 65 | try { 66 | jdbcTemplate.update("CREATE TABLE t_event (" + "id INT NOT NULL PRIMARY KEY," + "date TIMESTAMP," 67 | + "msg VARCHAR(255)" + ")"); 68 | 69 | System.out.println("Created table t_event"); 70 | } catch (DataAccessException e) { 71 | Throwable causeException = e.getCause(); 72 | if (causeException instanceof SQLException) { 73 | SQLException sqlException = (SQLException) causeException; 74 | if (sqlException.getSQLState().equals(SQL_ERROR_STATE_TABLE_EXISTS)) { 75 | System.out.println("Table already exists"); 76 | } else { 77 | throw e; 78 | } 79 | } else { 80 | throw e; 81 | } 82 | } 83 | } 84 | 85 | private void updateEventAutoId() { 86 | int maxId = getMaxId(); 87 | Event.initAutoId(maxId + 1); 88 | System.out.println("Initialized Event.AUTO_ID to " + maxId); 89 | } 90 | 91 | private int getMaxId() { 92 | Integer count = jdbcTemplate.queryForObject("select max(id) from t_event", Integer.class); 93 | return count != null ? count.intValue() : 0; 94 | } 95 | 96 | @Override 97 | public void logEvent(Event event) { 98 | jdbcTemplate.update("INSERT INTO t_event (id, date, msg) VALUES (?,?,?)", event.getId(), event.getDate(), 99 | event.toString()); 100 | System.out.println("Saved to DB event with id " + event.getId()); 101 | } 102 | 103 | public int getTotalEvents() { 104 | Integer count = jdbcTemplate.queryForObject("select count(*) from t_event", Integer.class); 105 | return count != null ? count.intValue() : 0; 106 | } 107 | 108 | public List getAllEvents() { 109 | List list = jdbcTemplate.query("select * from t_event", new RowMapper() { 110 | @Override 111 | public Event mapRow(ResultSet rs, int rowNum) throws SQLException { 112 | Integer id = rs.getInt("id"); 113 | Date date = rs.getDate("date"); 114 | String msg = rs.getString("msg"); 115 | Event event = new Event(id, new Date(date.getTime()), msg); 116 | return event; 117 | } 118 | }); 119 | return list; 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/loggers/EventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import com.yet.spring.core.beans.Event; 4 | 5 | public interface EventLogger { 6 | 7 | public void logEvent(Event event); 8 | 9 | public String getName(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/loggers/FileEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import org.apache.commons.io.FileUtils; 7 | 8 | import com.yet.spring.core.beans.Event; 9 | 10 | public class FileEventLogger extends AbstractLogger { 11 | 12 | private File file; 13 | 14 | private String filename; 15 | 16 | public FileEventLogger(String filename) { 17 | this.filename = filename; 18 | } 19 | 20 | public void init() throws IOException { 21 | file = new File(filename); 22 | if (file.exists() && !file.canWrite()) { 23 | throw new IllegalArgumentException("Can't write to file " + filename); 24 | } else if (!file.exists()) { 25 | file.createNewFile(); 26 | } 27 | } 28 | 29 | @Override 30 | public void logEvent(Event event) { 31 | try { 32 | FileUtils.writeStringToFile(file, event.toString() + "\n", true); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/util/AwareBean.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.BeanNameAware; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.ApplicationContextAware; 7 | import org.springframework.context.ApplicationEventPublisher; 8 | import org.springframework.context.ApplicationEventPublisherAware; 9 | 10 | public class AwareBean implements ApplicationContextAware, BeanNameAware, 11 | ApplicationEventPublisherAware { 12 | 13 | private ApplicationEventPublisher eventPublisher; 14 | private String name; 15 | private ApplicationContext ctx; 16 | 17 | public void init() { 18 | System.out.println(this.getClass().getSimpleName() + " > My name is '" 19 | + name + "'"); 20 | if (ctx != null) { 21 | System.out.println(this.getClass().getSimpleName() 22 | + " > My context is " + ctx.getClass().toString()); 23 | } else { 24 | System.out.println(this.getClass().getSimpleName() 25 | + " > Context is not set"); 26 | } 27 | if (eventPublisher != null) { 28 | System.out.println(this.getClass().getSimpleName() 29 | + " > My eventPublisher is " 30 | + eventPublisher.getClass().toString()); 31 | } else { 32 | System.out.println(this.getClass().getSimpleName() 33 | + " > EventPublisher is not set"); 34 | } 35 | } 36 | 37 | @Override 38 | public void setApplicationEventPublisher(ApplicationEventPublisher ep) { 39 | this.eventPublisher = ep; 40 | } 41 | 42 | @Override 43 | public void setBeanName(String name) { 44 | this.name = name; 45 | } 46 | 47 | @Override 48 | public void setApplicationContext(ApplicationContext context) 49 | throws BeansException { 50 | this.ctx = context; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/yet/spring/core/util/Monitor.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.util; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | import org.springframework.context.ApplicationListener; 5 | 6 | public class Monitor implements ApplicationListener { 7 | 8 | @Override 9 | public void onApplicationEvent(ApplicationEvent event) { 10 | System.out.println(event.getClass().getSimpleName() + " > " + event.getSource().toString()); 11 | }; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/aspects.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main/resources/client.properties: -------------------------------------------------------------------------------- 1 | id=1 2 | name=John Smith 3 | greeting=Hello there! -------------------------------------------------------------------------------- /src/main/resources/db.properties: -------------------------------------------------------------------------------- 1 | jdbc.driverClassName=org.apache.derby.jdbc.EmbeddedDriver 2 | jdbc.url=jdbc:derby:target/db;create=true 3 | jdbc.username=aa 4 | jdbc.password=bb -------------------------------------------------------------------------------- /src/main/resources/db.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/resources/loggers.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 15 | 16 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/resources/spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/TestApp.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertNull; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | import java.lang.reflect.InvocationTargetException; 9 | import java.lang.reflect.Method; 10 | import java.text.DateFormat; 11 | import java.util.Collections; 12 | import java.util.Date; 13 | import java.util.HashMap; 14 | 15 | import org.junit.Test; 16 | 17 | import com.yet.spring.core.beans.Client; 18 | import com.yet.spring.core.beans.Event; 19 | import com.yet.spring.core.beans.EventType; 20 | import com.yet.spring.core.loggers.AbstractLogger; 21 | import com.yet.spring.core.loggers.EventLogger; 22 | 23 | public class TestApp { 24 | 25 | private static final String MSG = "Hello"; 26 | 27 | @Test 28 | public void testClientNameSubstitution() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { 29 | Client client = new Client("25", "Bob"); 30 | DummyLogger dummyLogger = new DummyLogger(); 31 | 32 | App app = new App(client, dummyLogger, Collections.emptyMap()); 33 | 34 | Event event = new Event(new Date(), DateFormat.getDateTimeInstance()); 35 | 36 | invokeLogEvent(app, null, event, MSG + " " + client.getId()); 37 | assertTrue(dummyLogger.getEvent().getMsg().contains(MSG)); 38 | assertTrue(dummyLogger.getEvent().getMsg().contains(client.getFullName())); 39 | 40 | invokeLogEvent(app, null, event, MSG + " 0"); 41 | assertTrue(dummyLogger.getEvent().getMsg().contains(MSG)); 42 | assertFalse(dummyLogger.getEvent().getMsg().contains(client.getFullName())); 43 | } 44 | 45 | @Test 46 | public void testCorrectLoggerCall() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { 47 | Client client = new Client("25", "Bob"); 48 | DummyLogger defaultLogger = new DummyLogger(); 49 | DummyLogger infoLogger = new DummyLogger(); 50 | 51 | @SuppressWarnings("serial") 52 | App app = new App(client, defaultLogger, new HashMap() {{ 53 | put(EventType.INFO, infoLogger); 54 | }}); 55 | 56 | Event event = new Event(new Date(), DateFormat.getDateTimeInstance()); 57 | 58 | invokeLogEvent(app, null, event, MSG + " " + client.getId()); 59 | assertNotNull(defaultLogger.getEvent()); 60 | assertNull(infoLogger.getEvent()); 61 | 62 | defaultLogger.setEvent(null); 63 | infoLogger.setEvent(null); 64 | 65 | invokeLogEvent(app, EventType.ERROR, event, MSG + " " + client.getId()); 66 | assertNotNull(defaultLogger.getEvent()); 67 | assertNull(infoLogger.getEvent()); 68 | 69 | defaultLogger.setEvent(null); 70 | infoLogger.setEvent(null); 71 | 72 | invokeLogEvent(app, EventType.INFO, event, MSG + " 0"); 73 | assertNull(defaultLogger.getEvent()); 74 | assertNotNull(infoLogger.getEvent()); 75 | } 76 | 77 | private void invokeLogEvent(App app, EventType type, Event event, String message) throws NoSuchMethodException, 78 | IllegalAccessException, InvocationTargetException { 79 | Method method = app.getClass().getDeclaredMethod("logEvent", EventType.class, Event.class, String.class); 80 | method.setAccessible(true); 81 | method.invoke(app, type, event, message); 82 | } 83 | 84 | private class DummyLogger extends AbstractLogger { 85 | 86 | private Event event; 87 | 88 | @Override 89 | public void logEvent(Event event) { 90 | this.event = event; 91 | } 92 | 93 | public Event getEvent() { 94 | return event; 95 | } 96 | 97 | public void setEvent(Event event) { 98 | this.event = event; 99 | } 100 | 101 | }; 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/TestContext.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.util.Collection; 6 | import java.util.List; 7 | import java.util.stream.Collectors; 8 | 9 | import org.junit.BeforeClass; 10 | import org.junit.Test; 11 | import org.springframework.context.ConfigurableApplicationContext; 12 | import org.springframework.context.support.ClassPathXmlApplicationContext; 13 | 14 | import com.yet.spring.core.beans.Client; 15 | import com.yet.spring.core.loggers.EventLogger; 16 | 17 | public class TestContext { 18 | 19 | @BeforeClass 20 | public static void initTestDbProps() { 21 | System.setProperty("DB_PROPS", "classpath:db_for_test.properties"); 22 | } 23 | 24 | @Test 25 | public void testPropertyPlaceholderSystemOverride() { 26 | System.setProperty("id", "35"); 27 | ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml", 28 | "loggers.xml", "db.xml"); 29 | Client client = ctx.getBean(Client.class); 30 | ctx.close(); 31 | 32 | assertEquals("35", client.getId()); 33 | } 34 | 35 | @Test 36 | public void testLoggersNames() { 37 | ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml", 38 | "loggers.xml", "db.xml"); 39 | 40 | EventLogger fileLogger = ctx.getBean("fileEventLogger", EventLogger.class); 41 | EventLogger cacheLogger = ctx.getBean("cacheFileEventLogger", EventLogger.class); 42 | EventLogger combinedLogger = ctx.getBean("combinedEventLogger", EventLogger.class); 43 | 44 | @SuppressWarnings("unchecked") 45 | List combinedLoggers = ctx.getBean("combinedLoggersList", List.class); 46 | 47 | assertEquals(fileLogger.getName() + " with cache", cacheLogger.getName()); 48 | 49 | Collection combinedNames = combinedLoggers.stream() 50 | .map(v -> v.getName()).collect(Collectors.toList()); 51 | 52 | assertEquals("Combined " + combinedNames, combinedLogger.getName()); 53 | 54 | ctx.close(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/aspects/TestConsoleLoggerLimitAspect.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.aspects; 2 | 3 | import com.yet.spring.core.beans.Event; 4 | import com.yet.spring.core.loggers.EventLogger; 5 | import org.aspectj.lang.ProceedingJoinPoint; 6 | import org.junit.Test; 7 | 8 | import static org.mockito.Mockito.*; 9 | 10 | public class TestConsoleLoggerLimitAspect { 11 | 12 | @Test 13 | public void testAroundLogEvent() throws Throwable { 14 | ProceedingJoinPoint jp = mock(ProceedingJoinPoint.class); 15 | EventLogger mockLogger = mock(EventLogger.class); 16 | Event mockEvent = mock(Event.class); 17 | 18 | when(mockLogger.getName()).thenReturn("MockLogger"); 19 | 20 | ConsoleLoggerLimitAspect aspect = new ConsoleLoggerLimitAspect(2, mockLogger); 21 | 22 | aspect.aroundLogEvent(jp, mockEvent); 23 | aspect.aroundLogEvent(jp, mockEvent); 24 | aspect.aroundLogEvent(jp, mockEvent); 25 | 26 | verify(jp, atMost(2)).proceed(); 27 | verify(mockLogger, atMost(1)).logEvent(mockEvent); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/aspects/TestStatisticsAspect.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.aspects; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.mockito.Mockito.atMost; 5 | import static org.mockito.Mockito.mock; 6 | import static org.mockito.Mockito.verify; 7 | import static org.mockito.Mockito.when; 8 | 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | import org.aspectj.lang.JoinPoint; 13 | import org.junit.Test; 14 | 15 | import com.yet.spring.core.loggers.CombinedEventLogger; 16 | import com.yet.spring.core.loggers.ConsoleEventLogger; 17 | 18 | 19 | public class TestStatisticsAspect { 20 | 21 | @Test 22 | public void testStatisticCounter() { 23 | JoinPoint jp = mock(JoinPoint.class); 24 | 25 | when(jp.getTarget()).thenReturn(new ConsoleEventLogger()) 26 | .thenReturn(new CombinedEventLogger(Collections.emptyList())) 27 | .thenReturn(new ConsoleEventLogger()); 28 | 29 | StatisticsAspect aspect = new StatisticsAspect(); 30 | 31 | aspect.count(jp); 32 | aspect.count(jp); 33 | aspect.count(jp); 34 | 35 | verify(jp, atMost(3)).getTarget(); 36 | 37 | Map, Integer> counters = aspect.getCounter(); 38 | assertEquals(2, counters.size()); 39 | assertEquals(2, counters.get(ConsoleEventLogger.class).intValue()); 40 | assertEquals(1, counters.get(CombinedEventLogger.class).intValue()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/beans/TestEvent.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.beans; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.text.DateFormat; 6 | import java.util.Date; 7 | 8 | import org.junit.Test; 9 | 10 | import com.yet.spring.core.beans.Event; 11 | 12 | public class TestEvent { 13 | 14 | @Test 15 | public void testToString() { 16 | Date date = new Date(); 17 | DateFormat format = DateFormat.getDateInstance(); 18 | 19 | Event event = new Event(date, format); 20 | 21 | String str = event.toString(); 22 | assertTrue(str.contains(format.format(date))); 23 | } 24 | 25 | @Test 26 | public void testToString2() { 27 | Date date = new Date(); 28 | DateFormat format = DateFormat.getDateTimeInstance(); 29 | 30 | Event event = new Event(date, format); 31 | 32 | String str = event.toString(); 33 | assertTrue(str.contains(format.format(date))); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/loggers/TestCacheFileEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.text.DateFormat; 9 | import java.util.Date; 10 | 11 | import org.apache.commons.io.FileUtils; 12 | import org.junit.After; 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import com.yet.spring.core.beans.Event; 17 | 18 | public class TestCacheFileEventLogger { 19 | 20 | private File file; 21 | 22 | @Before 23 | public void createFile() throws IOException { 24 | this.file = File.createTempFile("test", "CacheFileEventLogger"); 25 | } 26 | 27 | @After 28 | public void removeFile() { 29 | file.delete(); 30 | } 31 | 32 | @Test 33 | public void testLogEvent() throws IOException { 34 | Event event = new Event(new Date(), DateFormat.getDateInstance()); 35 | CacheFileEventLogger logger = new CacheFileEventLogger(file.getAbsolutePath(), 2); 36 | logger.init(); 37 | 38 | String contents = FileUtils.readFileToString(this.file); 39 | assertTrue("File is empty initially", contents.isEmpty()); 40 | 41 | logger.logEvent(event); 42 | 43 | contents = FileUtils.readFileToString(this.file); 44 | assertTrue("File is empty as events in cache", contents.isEmpty()); 45 | 46 | logger.logEvent(event); 47 | 48 | contents = FileUtils.readFileToString(this.file); 49 | assertFalse("File not empty, cache was dumped", contents.isEmpty()); 50 | } 51 | 52 | @Test 53 | public void testDestroy() throws IOException { 54 | Event event = new Event(new Date(), DateFormat.getDateInstance()); 55 | CacheFileEventLogger logger = new CacheFileEventLogger(file.getAbsolutePath(), 2); 56 | logger.init(); 57 | 58 | String contents = FileUtils.readFileToString(this.file); 59 | assertTrue("File is empty initially", contents.isEmpty()); 60 | 61 | logger.logEvent(event); 62 | 63 | contents = FileUtils.readFileToString(this.file); 64 | assertTrue("File is empty as events in cache", contents.isEmpty()); 65 | 66 | logger.destroy(); 67 | 68 | contents = FileUtils.readFileToString(this.file); 69 | assertFalse("File not empty, cache was dumped", contents.isEmpty()); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/loggers/TestCombinedEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import com.yet.spring.core.beans.Event; 4 | import org.junit.Assert; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | import java.util.Collection; 9 | import java.util.stream.Collectors; 10 | import java.util.stream.Stream; 11 | 12 | import static org.mockito.Mockito.atMost; 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.verify; 15 | 16 | public class TestCombinedEventLogger { 17 | 18 | private Collection loggers; 19 | 20 | @Before 21 | public void createLoggers() { 22 | loggers = Stream.of( 23 | mock(EventLogger.class), 24 | mock(EventLogger.class) 25 | ).collect(Collectors.toList()); 26 | } 27 | 28 | @Test 29 | public void testCallingAllLoggers() { 30 | Event event = mock(Event.class); 31 | 32 | CombinedEventLogger combinedEventLogger = new CombinedEventLogger(loggers); 33 | combinedEventLogger.logEvent(event); 34 | 35 | loggers.forEach(logger -> verify(logger, atMost(1)).logEvent(event)); 36 | } 37 | 38 | /* Do we really need this test of a setter?! :) */ 39 | @Test 40 | public void testAllLoggersReturnedInSetter() { 41 | CombinedEventLogger combinedEventLogger = new CombinedEventLogger(loggers); 42 | combinedEventLogger.getLoggers() 43 | .stream() 44 | .map(logger -> loggers.contains(logger)) 45 | .forEach(Assert::assertTrue); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/loggers/TestConsoleEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.PrintStream; 5 | import java.text.DateFormat; 6 | import java.util.Date; 7 | 8 | import org.junit.After; 9 | import org.junit.Assert; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | 13 | import com.yet.spring.core.beans.Event; 14 | import com.yet.spring.core.loggers.ConsoleEventLogger; 15 | 16 | public class TestConsoleEventLogger { 17 | 18 | private static final String MSG = "Message"; 19 | private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); 20 | 21 | private PrintStream stdout; 22 | 23 | @Before 24 | public void setUpStreams() { 25 | stdout = System.out; 26 | System.setOut(new PrintStream(outContent)); 27 | } 28 | 29 | @After 30 | public void cleanUpStreams() { 31 | System.setOut(stdout); 32 | } 33 | 34 | @Test 35 | public void testLogEvent() { 36 | ConsoleEventLogger logger = new ConsoleEventLogger(); 37 | Date date = new Date(); 38 | Event event = new Event(date, DateFormat.getDateTimeInstance()); 39 | event.setMsg(MSG); 40 | 41 | logger.logEvent(event); 42 | 43 | Assert.assertTrue(outContent.toString().contains(MSG)); 44 | 45 | Assert.assertEquals(event.toString().trim(), outContent.toString().trim()); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/loggers/TestDBLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.List; 6 | 7 | import org.junit.After; 8 | import org.junit.Before; 9 | import org.junit.BeforeClass; 10 | import org.junit.Test; 11 | import org.springframework.context.ConfigurableApplicationContext; 12 | import org.springframework.context.support.ClassPathXmlApplicationContext; 13 | 14 | import com.yet.spring.core.beans.Event; 15 | 16 | public class TestDBLogger { 17 | 18 | @BeforeClass 19 | public static void initTestDbProps() { 20 | System.setProperty("DB_PROPS", "classpath:db_for_test.properties"); 21 | Event.initAutoId(-1); 22 | } 23 | 24 | private ConfigurableApplicationContext ctx; 25 | 26 | @Before 27 | public void createContext() { 28 | ctx = new ClassPathXmlApplicationContext("spring.xml", 29 | "loggers.xml", "db.xml"); 30 | } 31 | 32 | @After 33 | public void closeContext() { 34 | ctx.close(); 35 | } 36 | 37 | 38 | @Test 39 | public void testEventAutoIdCounterSet() { 40 | Event event = new Event(null, null); 41 | assertTrue(event.getId() > -1); 42 | } 43 | 44 | @Test 45 | public void testSaveAndGet() { 46 | DBLogger dbLogger = ctx.getBean("dbLogger", DBLogger.class); 47 | 48 | Event event1 = ctx.getBean(Event.class); 49 | event1.setMsg("a"); 50 | 51 | dbLogger.logEvent(event1); 52 | 53 | int total = dbLogger.getTotalEvents(); 54 | assertEquals(1, total); 55 | 56 | Event event2 = ctx.getBean(Event.class); 57 | event2.setMsg("b"); 58 | 59 | dbLogger.logEvent(event2); 60 | 61 | total = dbLogger.getTotalEvents(); 62 | assertEquals(2, total); 63 | 64 | List allEvents = dbLogger.getAllEvents(); 65 | assertEquals(2, allEvents.size()); 66 | assertTrue(allEvents.contains(event1)); 67 | assertTrue(allEvents.contains(event2)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/com/yet/spring/core/loggers/TestFileEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.yet.spring.core.loggers; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.text.DateFormat; 9 | import java.util.Date; 10 | 11 | import org.apache.commons.io.FileUtils; 12 | import org.junit.After; 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import com.yet.spring.core.beans.Event; 17 | 18 | public class TestFileEventLogger { 19 | 20 | private File file; 21 | 22 | @Before 23 | public void createFile() throws IOException { 24 | this.file = File.createTempFile("test", "FileEventLogger"); 25 | } 26 | 27 | @After 28 | public void removeFile() { 29 | file.delete(); 30 | } 31 | 32 | @Test 33 | public void testInit() throws IOException { 34 | FileEventLogger logger = new FileEventLogger(file.getAbsolutePath()); 35 | logger.init(); 36 | } 37 | 38 | @Test(expected=IllegalArgumentException.class) 39 | public void testInitFail() throws IOException { 40 | file.setReadOnly(); 41 | FileEventLogger logger = new FileEventLogger(file.getAbsolutePath()); 42 | logger.init(); 43 | } 44 | 45 | @Test 46 | public void testLogEvent() throws IOException { 47 | Event event = new Event(new Date(), DateFormat.getDateInstance()); 48 | FileEventLogger logger = new FileEventLogger(file.getAbsolutePath()); 49 | logger.init(); 50 | 51 | String contents = FileUtils.readFileToString(this.file); 52 | assertTrue(contents.isEmpty()); 53 | 54 | logger.logEvent(event); 55 | 56 | contents = FileUtils.readFileToString(this.file); 57 | assertFalse(contents.isEmpty()); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/test/resources/db_for_test.properties: -------------------------------------------------------------------------------- 1 | jdbc.driverClassName=org.apache.derby.jdbc.EmbeddedDriver 2 | jdbc.url=jdbc:derby:memory:myDB;create=true 3 | jdbc.username=aa 4 | jdbc.password=bb --------------------------------------------------------------------------------