Aspect Oriented programming for Log4j automatic implementing method - aop

Using the AspectJ compiler how to add a logging code after and before the execution of all methods in particular class
where to write the below code and how to run
aspect AspectExample {
before() : execution(* Point.*(..)) {
logger.entering(thisJoinPointStaticPart.getSignature().getName(), thisJoinPointStaticPart.getSignature().getDeclaringType() );
} after() : execution(* Point.*(..)) {
logger.exiting(thisJoinPointStaticPart.getSignature().getName() , thisJoinPointStaticPart.getSignature().getDeclaringType() );
}
}

Related

Kotest test factory and beforeSpec

Update While searching for the optimal solution, I switched temporarily to an approach using a dedicated test factory that performs the init in combination with forAll. In this way, I don't have to repeat the init code in every test factory.
fun somePreStuffFactory() = funSpec {
beforeTest {
println("Do some init stuff here")
}
test("dummy test just to trigger beforeTest") {}
}
class MyTest : FunSpec({
runBlocking {
forAll(
row(MyTestFactory::someTest1),
row(MyTestFactory::someTest2)
) { testFactoryFunc ->
include(somePreStuffFactory())
include(testFactoryFunc())
}
}
})
End of update
I have a lot of tests inside test factories. Before running the tests inside a test factory, I need to do some initial setup in the beginning of each test factory, and the setup is the same for all test factories.
Problem is that beforeSpec is not invoked inside test factory, hence I'm currently using a dirty workaround by doing init stuff in the first test in each test factory. I would highly appreciate any advice on this.
The optimal solution would be to have a life-cycle hook inside the the test class that runs before each test factory.
Code to reproduce
class MyTest : FunSpec({
include(someTest1())
include(someTest2())
})
import io.kotest.core.spec.style.funSpec
object MyTestFactory {
fun someTest1() = funSpec {
beforeSpec {
/** Not invoked */
println("Hello from someTest1#beforeSpec")
}
test("Init stuff is done inside a test") {
/** some init here */
}
test("first test") {
println("Hello from first test")
}
test("second test") {
println("Hello from second test")
}
}
fun someTest2() = funSpec {
beforeSpec {
/** Not invoked */
println("Hello from someTest2#beforeSpec")
}
test("Init stuff is done inside a test") {
/** some init here */
}
test("third test") {
println("Hello from third test")
}
}
}
What I've tried so far
After bumping Kotest from 4.6.4 to 5.4.2, I was able to run the code in answer from #ocos. Problem is that BeforeSpecSample#beforeSpec is invoked just once, not for each test factory which is my requirement.
object BeforeSpecSample : BeforeSpecListener {
override suspend fun beforeSpec(spec: Spec) {
println("Hello from beforeSpec")
}
}
class MyTest : FunSpec({
extensions(BeforeSpecSample)
include(someTest1())
include(someTest2())
})
Update
After reading this GitHub issue, I successfully tested the following approach using a boolean var initialized andbeforeTest. It would have been nice if this approach could be used inside test class instead of inside each test factory, but without any life-cycle hooks for test factories, I don't see how that can be done.
fun someTest1() = funSpec {
var initialized = false
beforeTest {
if (!initialized) {
println("Hello from someTest1#beforeTest")
initialized = true
}
}
/** tests goes here */
}
Environment
Kotest 4.6.4, Kotlin 1.7.10, Micronaut 3.6.3
Kotest test factory doc
If you don't mind grouping everything inside a test factory in a context block, you could use a BeforeContainerListener for initialization:
object InitExtension : BeforeContainerListener {
override suspend fun beforeContainer(testCase: TestCase) {
if(testCase.parent == null) {
println("init stuff")
}
}
}
The if(testCase.parent == null) is just there to allow your factory to have other nested contexts that will not trigger an additional invocation of the initialization.
Then you can write your factory like this:
fun someTest1() = funSpec {
extension(InitExtension)
context("someTest1") {
test("first test") {
println("Hello from first test")
}
test("second test") {
println("Hello from second test")
}
}
}
The initialization in InitExtension will be called at the beginning of context someTest1, and can analogously be included in other test factories that can each be initialized by the same extension.
include is using only tests and extensions defined in your someTest()'s TestFactory. This is why beforeSpec not invoked.
You can register an extension in your MyTest. Here is an example.
// you may use object MyTestFactory : BeforeSpecListener
object BeforeSpecSample : io.kotest.core.listeners.BeforeSpecListener {
override suspend fun beforeSpec(spec: Spec) {
println("-> before spec <-")
}
}
class MyTest : FunSpec({
extensions(BeforeSpecSample)
include(someTest())
test("my test 1") { println("my test 1") }
})

ktor test faild with 'Response has already been sent'

I trying to create API with ktor.
Test for ktor api using JUnit5 and I need use the custom properties for database information in 'Application.conf' like below:
ktor {
deployment {
.....
}
application {
.....
}
database {
host = ${?DB_HOST}
user = ${?DB_USER}
pass = ${?DB_PASS}
}
}
I following official guidline for useing custom properties:
HoconApplicationConfig
private val testEnv = createTestEnvironment {
config = HoconApplicationConfig(ConfigFactory.load("application.conf"))
}
class MyTest {
#Test
fun Testing() {
withApplication(testEnv) {
handleRequest(HttpMethod.Get, "/foo").apply {
...
}
}
}
}
Succeed test when only one function in class, but defined second test function then test failed with Exception.
I want define multiple function to simplify the definition and checking in case of failure.
class MyTest {
#Test
fun Testing() {
withApplication(testEnv) {
handleRequest(HttpMethod.Get, "/foo").apply {
....
}
}
}
#Test
fun Testing2() {
withApplication(testEnv) {
handleRequest(HttpMethod.Get, "/foo/bar").apply {
...
}
}
}
}
io.ktor.server.engine.BaseApplicationResponse$ResponseAlreadySentException: Response has already been sent
I know all test will success using 'withTestApplication' but can't use the custom properties.
How can I use the custom properties, and define multiple test funcitons?
Environment:
macOS Big Sur 11.5
IntelliJ Ultimate 2021.1.3
kotlin 1.5.21
ktor 1.6.1
junit-jupiter 5.7.0
Sorry for bad English.
Best Regards.

Why can't you access companion object of reified type parameter?

In the below, since T is reified, I want to use it "almost as if it were a normal class" by accessing its companion object.
class Cls {
companion object {
fun method() { }
}
}
inline fun <reified T> func() {
T.method() // error
}
fun main() {
func<Cls>()
}
But fails with
Type parameter 'T' cannot have or inherit a companion object, so it cannot be on the left hand side of dot
So it seems that a significant amount of information is lost. I get the same error with and without reified. I was hoping a reified type parameter would a fuller generic implementation than Java's. I have a ton of experience in C++ templates.
I've found some workarounds (that are all pretty disappointing using reflection), but really I'm asking why this can't work.
I'm not sure this is answering all the questions, but it's too big for a comment.
First and as stated in the comments, the way the code is written, T is not necessarily a Cls so to allow this you'd need some changes:
open class Cls {
companion object {
fun method() { }
}
}
inline fun <reified T : Cls> func() {
}
open the class and let Kotlin know T is a Cls
However, even though it's inlined, this still wouldn't let you call the companion method because T has no companion. Even without generics:
open class Cls {
companion object {
fun method() { }
}
}
class Foo : Cls
fun main() = Foo.method() // doesn't work
Doesn't work because companions are not inherited. Why? It was a conscious decision by the Kotlin designers. As you know Kotlin aims to correct a lot of issues Java had and this was one.
Static methods in Java are bound at compile-time while overriding is based on dynamic binding at runtime. This becomes quite confusing when you mix both and Kotlin tried to avoid this. Here's an example:
class Cls {
public static void method() {
System.out.println("Cls' method");
}
}
class Foo extends Cls {
public static void method() {
System.out.println("Foo's method");
}
}
public class Main {
public static void main(String[] args) {
Cls parent = new Foo();
parent.method();
}
}
If method would truly be overridden it would print out Foo's method, but indeed this prints Cls' method. The reason is that there's no overriding, but there's shadowing happening. On the other hand, if the methods wouldn't be static, then you'd get Foo's method since it is indeed overridden. This apparently caused confusion amongst developers and Kotlin completely disallowed it.

Overriding an internal method with Decorator Design Pattern

I am writing an object-oriented code in which I am trying to use Decorator pattern to implement a variety of optimizations to be applied on a family of core classes at runtime. The main behaviour of core classes is a complex behaviour that is fully implemented in those classes, which indeed calls other internal methods to fulfill pieces of the task.
The decorators will only customize the internal methods which are called by the complex behaviour in core class.
Here is a pseudo-code of what I'm trying to reach:
interface I{
complex();
step1();
step2();
}
class C implements I{
complex(){
...
this.step1();
...
this.step2();
}
step1(){
...
}
step2(){
...
}
}
abstract class Decorator implements I{
I wrapped;
constructor(I obj){
this.wrapped = obj;
}
complex(){
this.wrapped.complex();
}
step1(){
this.wrapped.step1();
}
step2(){
this.wrapped.step2();
}
}
class ConcreteDecorator extends Decorator{
constructor(I obj){
super(obj);
}
step2(){
... // customizing step2()
}
}
There are a variety of customizations possible which could be combined together, and that is the main reason I'm using decorator pattern. otherwise I'll get to create dozens to hundred subtypes for each possible combination of customizations.
Now if I try to create object of the decorated class:
x = new C();
y = new ConcreteDecorator(x);
y.complex();
I expect the complex() method to be executed form the wrapped core object, while using the overridden step2() method from decorator. But it does not work this way as the complex() method in abstract decorator directly calls the method on core object which indeed skips the overridden step2() in decorator.
My overall goal is to enable the decorators only overriding one or few of the stepx() methods and that would be invoked by the complex() method which is already implemented in the core object and invokes all the steps.
Could this functionality be implemented using Decorator design pattern at all? If yes how, and if not what is the appropriate design pattern for tackling this problem.
Thanks.
I guess you could resolve that problem with Strategy pattern, where the Strategy interface includes the methods that are vary from class to class. Strategy interface may include as only one method as well as several depending on their nature.
interface IStrategy {
step1(IData data);
step2(IData data);
}
interface I {
complex();
}
class C implements I {
IData data
constructor(IStrategy strategy) {}
complex() {
...
this.strategy.step1(this.data);
...
this.strategy.step2(this.data);
}
}
class S1 implements IStrategy {
constructor(IStrategy strategy)
step1(IData data) {
}
step2(IData data) {
}
}
strategy1 = new S1();
c = new C(strategy1)
The issue you are facing is that in your application of the Decorator design pattern, because you are not decorating complex(), the call to complex() on a decorator object will be delegated to the decorated object, which has "normal" version of step2.
I think a more appropriate design pattern to solve your problem would be the Template Method design pattern.
In your case complex() would play the role of the template method, whose steps can be customized by subclasses. Instead of using composition, you use inheritance, and the rest stays more or less the same.
Here is a sample application of the Template Method design pattern to your context:
public interface I {
void complex();
void step1(); // Better to remove from the interface if possible
void step2(); // Better to remove from the interface if possible
}
// Does not need to be abstract, but can be
class DefaultBehavior implements I {
// Note how this is final to avoid having subclass
// change the algorithm.
public final void complex() {
this.step1();
this.step2();
}
public void step1() { // Default step 1
System.out.println("Default step 1");
}
public void step2() { // Default step 2
System.out.println("Default step 1");
}
}
class CustomizedStep2 extends DefaultBehavior {
public void step2() { // Customized step 2
System.out.println("Customized step 2");
}
}

What is the reason for twitter4j.StreamListner IllegalAccessError in Kotlin?

When implementing a twitter4j.StatusListner in Kotlin, I get the following IllegalAccessError and associated stack trace:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class twitter4j.StreamListener from class rxkotlin.rxextensions.TwitterExampleKt$observe$1
at rxkotlin.rxextensions.TwitterExampleKt$observe$1.subscribe(TwitterExample.kt:50)
at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
at io.reactivex.Observable.subscribe(Observable.java:10700)
at io.reactivex.Observable.subscribe(Observable.java:10686)
at io.reactivex.Observable.subscribe(Observable.java:10615)
at rxkotlin.rxextensions.TwitterExampleKt.main(TwitterExample.kt:8)
Produced by the following code:
val twitterStream = TwitterStreamFactory().instance
// See https://stackoverflow.com/questions/37672023/how-to-create-an-instance-of-anonymous-interface-in-kotlin/37672334
twitterStream.addListener(object : StatusListener {
override fun onStatus(status: Status?) {
if (emitter.isDisposed) {
twitterStream.shutdown()
} else {
emitter.onNext(status)
}
}
override fun onException(e: Exception?) {
if (emitter.isDisposed) {
twitterStream.shutdown()
} else {
emitter.onError(e)
}
}
// Other overrides.
})
emitter.setCancellable { twitterStream::shutdown }
If I don't use Rx, it makes the exception a bit simpler:
twitterStream.addListener(object: twitter4j.StatusListener {
override fun onStatus(status: Status) { println("Status: {$status}") }
override fun onException(ex: Exception) { println("Error callback: $ex") }
// Other overrides.
})
Exception in thread "main" java.lang.IllegalAccessError: tried to access class twitter4j.StreamListener from class rxkotlin.rxextensions.TwitterExampleKt
at rxkotlin.rxextensions.TwitterExampleKt.main(TwitterExample.kt:14)
However, if I implement a Java wrapper function, no error is thrown and the behaviour is as expected:
Wrapper -
public class Twitter4JHelper {
public static void addStatusListner(TwitterStream stream, StatusListener listner) {
stream.addListener(listner);
}
}
Revised implementation -
val twitterStream = TwitterStreamFactory().instance
val listner = object: StatusListener {
override fun onStatus(status: Status?) {
if (emitter.isDisposed) {
twitterStream.shutdown()
} else {
emitter.onNext(status)
}
}
override fun onException(e: Exception?) {
if (emitter.isDisposed) {
twitterStream.shutdown()
} else {
emitter.onError(e)
}
}
// Other overrides.
}
Twitter4JHelper.addStatusListner(twitterStream, listner)
emitter.setCancellable { twitterStream::shutdown }
This revised solution comes from a blog post, which I think tries to explain the cause but Google translate is not being my friend. What is causing the IllegalAccessError? Is there a purely Kotlin based solution, or will I have to live with this workaround?
Yep that's not going to work.
addListener method takes a StreamListener param and StreamListener is non-public (package private). I would definitely raise a bug against Kotlin compiler for this.
The code Kotlin compiler generates is:
TwitterStream twitterStream = (new TwitterStreamFactory()).getInstance();
twitterStream.addListener((StreamListener)(new StatusListener() {
// ..overrides ...
}));
StatusListener already implements StreamListener so I don't see why the cast is required.
I worked around this by using a java utility class:
public class T4JCompat {
public static void addStatusListener(TwitterStream stream, StatusListener listener) {
stream.addListener(listener);
}
public static void removeStatusListener(TwitterStream stream, StatusListener listener) {
stream.removeListener(listener);
}
}
You can call these methods from Kotlin and things work as expected.