I would like to intercept calls to methods conversation.begin() and conversation.end().
To do this, I have developed an interceptor binding that I aim to dynamically assign to the Conversation class through a CDI portable extension.
However, I can not find how to access to the Conversation class since it is not observed in the ProcessAnnotatedType event where usually i do this process to my defined beans.
See the code as an example:
public class MethodCallsInterceptorExt implements Extension {
void processAnnotatedType(#Observes ProcessAnnotatedType<?> event) {
if (isConvesationBean(event)) { // This condition is never true
event.configureAnnotatedType().add(new MyInterceptorBinding());
}
}
}
Is this solution at least partially correct?
Is there any viable way to do this?
You could do something like this:
public class ConversationObserver {
public void onStart(#Observes #Initialized(ConversationScoped.class) ServletRequest request) {}
public void onEnd(#Observes #Destroyed(ConversationScoped.class) ServletRequest request) {}
}
See https://docs.jboss.org/cdi/api/2.0/javax/enterprise/context/ConversationScoped.html
I have a simple scenario in which am trying to verify some behavior when a method is called (i.e. that a certain method was called with given parameter, a function pointer in this scenario). Below are my classes:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
AppBootStrapper bootStrapper = context.getBean(AppBootStrapper.class);
bootStrapper.start();
}
}
#Component
public class AppBootStrapper {
private NetworkScanner networkScanner;
private PacketConsumer packetConsumer;
public AppBootStrapper(NetworkScanner networkScanner, PacketConsumer packetConsumer) {
this.networkScanner = networkScanner;
this.packetConsumer = packetConsumer;
}
public void start() {
networkScanner.addConsumer(packetConsumer::consumePacket);
networkScanner.startScan();
}
}
#Component
public class NetworkScanner {
private List<Consumer<String>> consumers = new ArrayList<>();
public void startScan(){
Executors.newSingleThreadExecutor().submit(() -> {
while(true) {
// do some scanning and get/parse packets
consumers.forEach(consumer -> consumer.accept("Package Data"));
}
});
}
public void addConsumer(Consumer<String> consumer) {
this.consumers.add(consumer);
}
}
#Component
public class PacketConsumer {
public void consumePacket(String packet) {
System.out.println("Packet received: " + packet);
}
}
#RunWith(JUnit4.class)
public class AppBootStrapperTest {
#Test
public void start() throws Exception {
NetworkScanner networkScanner = mock(NetworkScanner.class);
PacketConsumer packetConsumer = mock(PacketConsumer.class);
AppBootStrapper appBootStrapper = new AppBootStrapper(networkScanner, packetConsumer);
appBootStrapper.start();
verify(networkScanner).addConsumer(packetConsumer::consumePacket);
verify(networkScanner, times(1)).startScan();
}
}
I want to verify that bootStrapper did in fact do proper setup by registering the packet consumer(there might be other consumers registered later on, but this one is mandatory) and then called startScan. I get the following error message when I execute the test case:
Argument(s) are different! Wanted:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapperTest$$Lambda$8/438123546#282308c3
);
-> at com.spring.starter.AppBootStrapperTest.start(AppBootStrapperTest.java:24)
Actual invocation has different arguments:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapper$$Lambda$7/920446957#5dda14d0
);
-> at com.spring.starter.AppBootStrapper.start(AppBootStrapper.java:12)
From the exception, clearly the function pointers aren't the same.
Am I approaching this the right way? Is there something basic I am missing? I played around and had a consumer injected into PacketConsumer just to see if it made a different and that was OK, but I know that's certainly not the right way to go.
Any help, perspectives on this would be greatly appreciated.
Java doesn't have any concept of "function pointers"; when you see:
networkScanner.addConsumer(packetConsumer::consumePacket);
What Java actually compiles is (the equivalent of):
networkScanner.addConsumer(new Consumer<String>() {
#Override void accept(String packet) {
packetConsumer.consumePacket(packet);
}
});
This anonymous inner class happens to be called AppBootStrapper$$Lambda$7. Because it doesn't (and shouldn't) define an equals method, it will never be equal to the anonymous inner class that the compiler generates in your test, which happens to be called AppBootStrapperTest$$Lambda$8. This is regardless of the fact that the method bodies are the same, and are built in the same way from the same method reference.
If you generate the Consumer explicitly in your test and save it as a static final Consumer<String> field, then you can pass that reference in the test and compare it; at that point, reference equality should hold. This should work with a lambda expression or method reference just fine.
A more apt test would probably verify(packetConsumer, atLeastOnce()).consumePacket(...), as the contents of the lambda are an implementation detail and you're really more concerned about how your component collaborates with other components. The abstraction here should be at the consumePacket level, not at the addConsumer level.
See the comments and answer on this SO question.
We have few rules, which are Implemented as methods in Java. But sometimes we need to bypass the rules. So for each rule, we have a boolean Indicator to indicate whether to execute or not. What can be a good design to map the methods to boolean values in Database and execute methods based on the boolean values.
Below is sample template
1 Rule1 true
2 Rule2 false
3 Rule3 true
4 Rule4 true
So, now I need to execute method1(), method3() and method4() respectively.
One Simple way can be using If(rulee == true) executeMethod();
Second is using a Switch to execute the cases (method calls)
Note: We may need to execute the methods in different locations(methods). So please dont consider that all the methods will be called from a single method.
Can I make use of AOP by any chance?
You could define the basic interface as
public interface Rule {
boolean canExecute();
void execute();
}
and convert the methods into Rule interface implementations. The boolean value in the database would map to canExecute() return value.
This would be a good idea if methods are becoming complex, there's more than a few of them and the parent class is starting to look like a God Object.
Use Java 8 Stream api and Enums.
public class Main {
public enum Rule {
RULE1 {
#Override
public void doWork() {
}
},
RULE2 {
#Override
public void doWork() {
}
};
public abstract void doWork();
}
public static void main(String[] args) {
List<String> rules = new ArrayList<>();
rules.stream()
.map(Rule::valueOf)
.forEach(Rule::doWork);
}
}
You can just call all methods and do the validation part within the method implementation, e.g.:
void rule1(Object... args){
if (!applyRule1){
return;
}
...
}
With that approach, you can reduce cyclomatic complexity and prevent tools such as PMD from complaining.
Another approach is to store the method names as strings in the database. If your database supports arrays, that's particularly easy.
Then in Java you can set up an executor that accepts a String name and execute the respective rule:
import java.util.List;
import static java.util.Arrays.asList;
public class ByNameExecutor {
enum Rule {
Rule1 { #Override void rule() { System.out.println("Executed rule 1"); } },
Rule2 { #Override void rule() { System.out.println("Executed rule 2"); } },
Rule3 { #Override void rule() { System.out.println("Executed rule 3"); } },
Rule4 { #Override void rule() { System.out.println("Executed rule 4"); } },
;
abstract void rule();
}
public void execute(String ruleName) {
Rule.valueOf(ruleName).rule();
}
public void execute(List<String> ruleNames) {
ruleNames.stream().forEach(this::execute);
}
public static void main(String [] args) {
String [] methodList = { "Rule1", "Rule2", "Rule4" };
new ByNameExecutor().execute(asList(methodList));
}
}
An advantage of this approach is that you don't need to change the database schema to add a rule. Just start storing the new rule's string name. A disadvantage is that if you need to query on presence of or absence of a given rule, the database must support indexes over arrays.
Update: I replaced Consumer interface with Runnable in my original answer, because it aligns with example in the question better.
You can try to upgrade your Rule entity, here is an idea using Runnable interface:
class Rule {
private boolean isActive;
private Runnable runnable;
public Rule(boolean isActive, Runnable runnable) {
this.isActive = isActive;
this.runnable = runnable;
}
public void executeIfActive() {
if (isActive) {
runnable.run();
isActive = false;
}
}
}
Example of the use:
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
List<Rule> rules = List.of(new Rule(true, demo::m1), new Rule(false, demo::m2));
rules.forEach(Rule::executeIfActive);
}
void m1() { ... }
void m2() { ... }
}
demo::m1 is a method reference that would invoke the method demo.m1(), and the same for m2.
If I understand the problem correctly then it should work. You can have a method like below and call it from anywhere.
Or these booleans can also be a rule and you can add multiple methods in one IF condition
void executeMethods(boolean m1, boolean m2, boolean m3, boolean m4){
if(m1) m1();
if(m2) m2();
if(m3) m3();
if(m4) m4();
}
executeMethods(true,false,false,true);
Instead of store Boolean you can store method names in this field accordingly. Then all you need to do would be invoke that method using reflection.
Table:
Id RULE_NAME METHOD_NAME
1 Rule1 method1
2 Rule2
3 Rule3 method3
4 Rule4 method4
The method can be invoked like this:
ResultSet srs = stmt.executeQuery("SELECT METHOD_NAME from table");
while (srs.next()) {
String methodName = srs.getString("METHOD_NAME");
if (!TextUtils.isEmpty(methodName)) {
Class<?> c = Class.forName("class name");
Method method = c.getDeclaredMethod(methodName, parameterTypes); // method name will be fetched from Database
method.invoke(objectToInvokeOn, params);
}
}
Reflection API > Invoking Methods
Lets solve this problem with a database driven approach, and Spring AOP.
You have several hundred rules, and do not wish to pollute the current code with boilerplate code like void method1() { if (!rule1) return; .. do method } or have to create additional interfaces which all rule based methods must implement.
Spring AOP provides a means to leave the current base in tact, and instead have methods intercepted (via a proxy) to determine if the method should run or not. You write the proxy code once, and the only ongoing requirement is to keep the database up to date with new rules.
Step 1: Build a database schema which maps method names to boolean values
method_name VARCHAR(100), is_rule_active tinyint(1);
There will be one row for each rule. The row will contain the method name (as it appears in the java code) and a boolean true=active, false=not active.
Step 2: Build an interface to the database (DAO)
You need a simple abstraction to the database. Something like:
public interface RuleSelectionInterface {
boolean isRuleActive(String methodName);
}
The implementation will be basic DAO code, which will query for the row with method_name equal to methodName. For simplicity, and to demonstrate, I used a Map instead:
#Repository
public class RuleSelectionImpl implements RuleSelectionInterface {
Map<String, Boolean> rules;
public RuleSelectionImpl() {
rules = new HashMap<>();
rules.put("rule1Method", true);
rules.put("rule2Method", false);
}
#Override
public boolean isRuleActive(String methodName) {
if (!rules.containsKey(methodName))
return false;
return rules.get(methodName);
}
}
Step 3: Create a Spring AOP aspect
An aspect is created to intercept method calls, and determine when the call should be executed.
To allow execution to be continued, or aborted, you use an #Around advice, which will be passed the execution point (by means of a ProceedingJoinPoint) from which you can either abort (the proxy method simply returns) or run the code by using the proceed method.
There is some choice here on which methods should be intercepted (this is done by defining pointcuts). This example will intercept methods with names starting with rule:
#Around("execution(* rule*(..))")
You could intercept all methods, or methods based on naming patterns, etc. For a detailed understanding of how to create pointcuts to intercept methods refer to Spring AOP
Here is the AOP code, which is called upon method interception, and which uses your database rule interface to look up if the rule is active for this method name:
#Aspect
#Component
public class RuleAspects {
#Autowired
private RuleSelectionInterface rulesSelectionService;
#Around("execution(* rule*(..))")
public void ruleChooser(ProceedingJoinPoint jp) throws Throwable
{
Signature sig = jp.getSignature();
System.out.println("Join point signature = "+sig);
String methodName = sig.getName();
if (rulesSelectionService.isRuleActive(methodName))
jp.proceed();
else
System.out.println("Method was aborted (rule is false)");
}
}
Sample usage:
I created a simple class with two methods (however this approach works regardless of how many classes/methods you have rule based methods for).
#Component
public class MethodsForRules {
public void rule1Method() {
System.out.println("Rule 1 method");
}
public void rule2Method() {
System.out.println("Rule 2 method");
}
}
You will have noticed in the Map that rule1Method is set to true, and rule2Method is set to false.
When the code tries to run rule1Method and rule2Method:
MethodsForRules r; // Is a Spring managed bean.
r.rule1Method();
r.rule2Method();
Produces the following output:
Join point signature = void com.stackoverflow.aoparound.demo.MethodsForRules.rule1Method()
Rule 1 method <- Here is the method running
Join point signature = void
com.stackoverflow.aoparound.demo.MethodsForRules.rule2Method()
Method was aborted (rule is false) <- Here the method is aborted
Summary:
This demonstration has shown how Spring AOP can be used, in combination with a rules based interface, to intercept methods (by using a proxy), examine the method name which was intercepted, lookup the active status for this method, and either run the method, or abort it.
I have the following problem with Guice: a singleton service, is injected with provider of context-sensitive information. Until now, context was related only to servlet requests, so I used a #RequestScoped provider, and I was injecting this provider in service like so:
#RequestScoped
public class ContextProvider<IContext> implements Provider<IContext> {
#Override
public IContext get() { ... } // returns context
}
#Singleton
public class ServiceImpl implements IService {
#Inject
private Provider<IContext> contextProvider;
}
That works fine. Now, I'm working on adding background task processing to the application. Background tasks are not initiated from web-requests, so I can not use ServletScopes.scopeRequest(..). I have written a custom scope (almost exact copy of BatchScoped from Giuce doc) to make each Task run in it's own scope. Now the question is - how to make BatchScoped ContextProvider and configure Guice to use it?
I've made this attempt with binding EDSL:
line 1 : bind(IContext.class).toProvider(ContextProvider.class).in(RequestScoped.class);
line 2 : bind(IContext.class).toProvider(BatchContextProvider.class).in(BatchScoped.class);
but Guice tells me at line 2 that 'A binding to IContext was already configured at line 1'.
The question is: what's the right way of doing such injection with Guice?
A similar question: Getting multiple guice singletons of the same type
In general the problem here is that you want to bind the same class to two different providers (and scopes, but that's actually beside the point). That is only possible if you use unique binding annotations for each one, like so:
bind(IContext.class)
.annotatedWith(MyAnnotation1.class)
.toProvider(ContextProvider.class)
.in(RequestScoped.class);
bind(IContext.class)
.annotatedWith(MyAnnotation2.class)
.toProvider(BatchContextProvider.class)
.in(BatchScoped.class);
And change injection sites to include relevant annotation:
#Inject
#MyAnnotationX
private Provider<IContext> contextProvider;
You need a fake request that starts with your background task and remains for all of it. That is what ServletScopes.scopeRequest does.
public class MyBackgroundTask extends Thread {
#Override
public void run() {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
doTask();
}
}
private void doTask() {
}
}
Oh, don't forget to use providers so you delay the retrieval of your dependencies. For example, expading the previous example so the background task uses your IContext.
public class MyBackgroundTask extends Thread {
private Provider<IContext> contextProvider;
#Inject
public MyBackgroundTask(Provider<IContext> contextProvider) {
this.contextProvider = contextProvider;
}
#Override
public void run() {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
doTask();
}
}
private void doTask() {
}
}
If you don't use providers the injection, in this example, will be done from the thread that creates the background task which could be inside another scope.
BONUS: You may have noticed the empty map sent as a parameter to the scopeRequest method. Check the Guice javadocs. Those are the instances that you want already present in your fake request scope. Depending on your IContext you may need it.
I'm writing a test suite, and I'm thinking about how to mock certain request/response flows. For example, I want to test a method that makes multiple RESTful calls:
getCounts() {
...
Promise<Integer> count1 = getCount1();
Promise<Integer> count2 = getCount2();
// returns a DataModel containing all counts when the Promises redeem
}
getCount1() {
...
Request<Foo> request = new Request<Foo>();
sendRequest(request);
...
}
getCount2() {
...
Request<Bar> request = new Request<Bar>();
sendRequest(request);
...
}
sendRequest(Request<T> request) {...}
However, each getCount() method creates a different Request<T> object, where <T> describes the type of request being made in regards to the count being retrieved. This means I can't simply "mock" the sendRequest() method since it is being called with a different type each time.
I was thinking about an approach where I register a "handler"... when sendRequest() is called, it determines which handler to call, and the handler would know the appropriate type of mock data to return. The registration would be something like storing the handler class type or an instance of the handler class along with the mock data it needs, and when sendRequest() is called, it would look for and invoke the correct handler.
However, I'm not sure if this a good pattern, and I'm wondering if there is a better way of approaching this problem. What is a good pattern for registering a Class or a particular method to execute a specific task later on?
Hard to answer without more context, but the general approach is to use Inversion Of Control (IOC). For example, put the getCountXXX methods into a class of their own, which may be a good idea for better reuse, readability, encapsulation, testability, etc:
public class CountFetcher {
getCount1() { ... }
getCount2() { ... }
}
The original code now gets an instance of CountFetcher using whatever "injection" mechanism is available to you. Simplest is just a constructor:
public class Counter {
private final CountFetcher fetcher;
public Counter(CountFetcher fetcher) {
this.fetcher = fetcher;
}
public getCounts() {
Promise<Integer> count1 = fetcher.getCount1();
Promise<Integer> count2 = fetcher.getCount2();
...
}
}
In your production code, you instantiate Counter with a real CountFetcher. In test code, you inject a mock version of CountFetcher which can have each individual getCountXXX method return whatever you want:
public class MockCountFetcher extends CountFetcher {
#Override
getCount1() { return mockCount1; }
}
public class TestCounter {
#Test
public void smokeTest() {
CountFetcher mockFetcher = new MockCountFetcher();
Counter counter = new Counter(mockFetcher);
assertEquals(someExpectedValue, counter.getCounts());
}
}