Commit 78e86c2c authored by Rajiv Prabhakar's avatar Rajiv Prabhakar
Browse files

v2.0.1 release:

- major logging update: all logging now done on log4j2-api
- Using log4j2 implementation locally, but not passed on to any library users
- log4j2 implementation-config file added to classpath. Auto-accessible by any library users who don't have their own config file
- README updates
parent b093eeb6
Pipeline #16300629 passed with stage
in 2 minutes and 52 seconds
......@@ -23,7 +23,7 @@ We don't believe in magic. We don't believe in doing anything smart or clever. W
Our goal is not performance. We will never optimize our implementations or interfaces for performance. Our goal is first and foremost to provide the user with the most convenient utility for their needs, and second, to implement this interface in a manner that makes maintenance as easy as possible.
Planned Obsolesence
Planned Obsolescence
--------------
In an ideal world, other libraries like ApacheCommons and Guava will make us obsolete. Whenever we find another library that is as clean and friendly as our own, we will deprecate our own implementation and refer our users to them instead. We exist only to cover up for others' failings, and we yearn for the day when this library will no longer be needed.
......@@ -31,14 +31,36 @@ In an ideal world, other libraries like ApacheCommons and Guava will make us obs
Features
=========
Convert any checked exceptions to run-time exceptions without altering the message/toString/stack-trace
--------------------------------------------------------------------------------------------------------
Validate external inputs and program state: Better error messages and user-specified exception in single line
-------------------------------------------------------------------------------------------------------------
Replace:
```java
if (!a.equals(b)) {
log.error("A: " + a + ", B: " + b);
throw new MyCustomException("Error!");
}
```
with:
```java
// Exception will be thrown only if check fails
Validatec.equals(a, b, new MyCustomException("Error!"));
```
or:
```java
// Exception will be constructed & thrown only if check fails
Validatec.equals(a, b, MyCustomException.class, "Error!");
```
Convert any checked exceptions to run-time exceptions without altering the stack-trace
----------------------------------------------------------------------------------------------
Replace:
```java
try {
method();
} catch (CheckedException e) {
throw new RunTimeException(e); // getStackTrace() differs from e.getStackTrace()
throw new RunTimeException(e); // stack-trace and cause modified, with noisy data
}
```
......@@ -47,7 +69,7 @@ With:
try {
method();
} catch (CheckedException e) {
throw new CheckedExceptionWrapper(e); // getStackTrace, getMessage, toString will return *exact same values*
throw new CheckedExceptionWrapper(e); // getStackTrace, getMessage, getCause will return *exact same values*
}
```
......@@ -85,44 +107,6 @@ with:
ThreadUtilc.sleep(10);
```
Validate external inputs and program state: Better error messages and user-specified exception
-------------
Replace:
```java
if (a != b) {
log.error("A: " + a + ", B: " + b);
throw new MyCustomException("Error!");
}
```
with:
```java
// Exception will be thrown only if check fails
Validatec.equals(a, b, new MyCustomException("Error!"));
```
or:
```java
// Exception will be constructed & thrown only if check fails
Validatec.equals(a, b, "Error!", MyCustomException.class);
```
Inline initialization of maps
-------------
Replace:
```java
Map<Integer, String> map = Maps.newHashMap();
map.add(1, "one");
map.add(2, "two");
map.add(3, "three");
return map;
```
with:
```java
return Mapc.newHashMap(1, "one", 2, "two", 3, "three");
```
Maven Installation
==================
......@@ -133,7 +117,7 @@ Add the following to your pom.xml file, and you should be good to go. Check [her
<dependency>
<groupId>com.rajivprab</groupId>
<artifactId>cava</artifactId>
<version>1.4.0</version>
<version>2.0.1</version>
</dependency>
</dependencies>
```
......
......@@ -6,7 +6,7 @@
<groupId>com.rajivprab</groupId>
<artifactId>cava</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
<name>Cava: Clean Java</name>
<description>A library that enables users to write minimal, clean and simple Java</description>
......@@ -40,11 +40,6 @@
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
......@@ -55,28 +50,41 @@
<artifactId>javatuples</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.2-jre</version>
</dependency>
<!-- Logging: log4j2 as API. Clients are free to use any implementation desired -->
<!-- https://stackoverflow.com/questions/41498021/is-it-worth-to-use-slf4j-with-log4j2/41500347#41500347 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
</dependency>
<!-- log4j2 as implementation for local testing. Test scope: Do not force implementation on users. -->
<!-- Warning: Using both log4j2:slf4j and slf4j:log4j2 will cause infinite loop -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
<scope>test</scope>
</dependency>
<!-- TODO Major can of worms here. Use slf4j + log4j? Or Apache.commons.logging + log4j?
Maven central snippets recommends using test scope here, but what does that mean for other projects like caucus?
Does that mean that the log4j.properties will be applied only when running tests, and not in prod?
If test scope is applied below, will I need to manually copy-paste this dependency in all my other projects?
If I'm using apache.commons.logging (ie, LogFactory.getLog()), then why am I using this slf4j-log4j below? -->
<!-- For any usages of slf4j by other libraries, use log4j2 as the implementation -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.10.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.2-jre</version>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
......
package org.rajivprab.cava;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.time.Duration;
import java.util.concurrent.*;
......@@ -12,7 +12,7 @@ import java.util.concurrent.*;
* Created by rprabhakar on 12/15/15.
*/
public class ThreadUtilc {
private static final Log log = LogFactory.getLog(ThreadUtilc.class);
private static final Logger log = LogManager.getLogger(ThreadUtilc.class);
// ---------- Sleep ------------
......
package org.rajivprab.cava;
import com.google.common.base.Strings;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.javatuples.Pair;
import org.javatuples.Triplet;
......@@ -18,7 +18,7 @@ import java.util.Map;
* Created by rprabhakar on 12/15/15.
*/
public class Validatec {
private static final Log log = LogFactory.getLog(Validatec.class);
private static final Logger log = LogManager.getLogger(Validatec.class);
private static final Class<? extends RuntimeException> DEFAULT_EXCEPTION = IllegalArgumentException.class;
// ------------------------- Is true ----------------------------
......@@ -102,6 +102,8 @@ public class Validatec {
}
}
// GetMessage methods like this one, can require O(N) time to generate the message.
// Make sure this only gets invoked if the check fails, and not if the check succeeds.
private static String getSizeMessage(Collection collection, int size) {
return collection + " should have " + size + " entries";
}
......
# Set root logger level to INFO and its only appender to A1.
log4j.rootLogger=INFO, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-5p %c{3} %d{yyyy_MM_dd_HH:mm} - %m%n
# https://logging.apache.org/log4j/2.x/manual/configuration.html
# Print all log4j2 status-messages of INFO or higher
status = info
# Console appender, which uses specified pattern
appender.console.type = Console
appender.console.name = CavaConsoleAppender
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm z}{UTC}] %-5p %c{2} - %m%n
# By default, all logs will be routed to above CavaConsoleAppender, with min-threshold of INFO
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = CavaConsoleAppender
# TODO Enhancement: Instructions for async logging
# https://logging.apache.org/log4j/2.x/manual/async.html
\ No newline at end of file
......@@ -2,8 +2,6 @@ package org.rajivprab.cava;
import com.google.common.collect.Lists;
import com.google.common.truth.Truth;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.Assert;
......@@ -20,8 +18,6 @@ import java.util.stream.Collectors;
* Created by rprabhakar on 7/29/15.
*/
public class JsonUtilcTest extends TestBase {
private static final Log log = LogFactory.getLog(JsonUtilcTest.class);
@Test
public void mergeAllObjectsIntoArray() {
JSONArray jsonArray = JsonUtilc.mergeAllObjectsIntoArray(Lists.newArrayList("one", "two", "three"));
......
package org.rajivprab.cava;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Ignore;
/**
* General config that might be needed by all other unit tests
*
* Created by rprabhakar on 1/31/16.
*/
public class TestBase {
protected static final Logger log = LogManager.getLogger(TestBase.class);
@Ignore
public void loggerShouldPrintInfoAndAbove() {
log.fatal("fatal message");
log.error("error message");
log.warn("warn message");
log.info("info message");
log.debug("debug message");
log.trace("trace message");
}
}
......@@ -23,7 +23,7 @@ import java.util.stream.IntStream;
* Created by rprabhakar on 12/22/15.
*/
public class ThreadUtilcTest extends TestBase {
private static final Duration TEST_DURATION = Duration.ofSeconds(1);
private static final Duration TEST_DURATION = Duration.ofMillis(2000);
private static final int RETURN_VALUE = 42;
private static final Random RNG = new Random();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment