Weld SE: not injecting inner dependency in Junit Test - weld

I am using Weld SE in a junit test. It seems it does not inject an inner field of a CDI bean. I am using the maven artifcat weld-se-shaded (4.0.2-Final)
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class XService {
#Override
public String toString() {
return "hi from XService";
}
}
// ---
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class YService {
#Override
public String toString() {
return "hi from YService";
}
}
// ---
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
#ApplicationScoped
public class ZService {
#Inject
public YService yService;
#Override
public String toString() {
return "hi from ZService";
}
}
// ---
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class WeldTest {
private WeldContainer container;
#Before
public void startContainer() {
Weld weld = new Weld();
weld.disableDiscovery();
weld.addBeanClasses(XService.class, YService.class, ZService.class);
container = weld.initialize();
}
#After
public void stopContainer() {
container.shutdown();
}
#Test
public void shouldCreateXServiceInstance() {
// ok
XService xService = container.select(XService.class).get();
assertThat(xService.toString()).isEqualTo("hi from XService");
}
#Test
public void shouldCreateYServiceInstance() {
// ok
YService yService = container.select(YService.class).get();
assertThat(yService.toString()).isEqualTo("hi from YService");
}
#Test
public void shouldInjectYServiceInZService() {
// fails
ZService zService = container.select(ZService.class).get();
assertThat(zService.toString()).isEqualTo("hi from ZService");
// yService is null, assertion fails
assertThat(zService.yService).isNotNull();
}
}
There is no exception, the field is just null. Instead of field injection I tried constructor injection:
#ApplicationScoped
public class ZService {
public YService yService;
#Inject
public ZService(YService yService) {
this.yService = yService;
}
#Override
public String toString() {
return "hi from ZService";
}
}
In that case I get an exception message: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type ZService with qualifiers

Seems that Weld 4 only considers jakarta.* imports. If I change javax.* imports to jakarta.* the example works. It also works if I am downgrading to Weld 3 with javax.* imports.

Related

Dagger generated code compilation failed when using #Singleton annotation

I am using Dagger - 2.6 and i have the following classes.
public class Trigger {
public static JSONObject triggerLambda(JSONObject jsonObject) {
DataTransformerComponent daggerDataTransformerComponent = DaggerDataTransformerComponent.create();
return daggerDataTransformerComponent.getHandler().handle(jsonObject);
}
}
Data Handler class:
public class DataHandler {
private static final Logger LOGGER = Logger.getLogger(DataHandler.class.getName());
private A a;
#Inject
public DataHandler(A a) {
this.a = a;
}
public JSONObject handle(JSONObject input) {
LOGGER.info("Json input received - " + input.toString());
return a.executeTransformation(input);
}
}
And a dependency:
public class A {
#Inject
public A() {
}
public JSONObject executeTransformation(JSONObject jsonObject) {
System.out.println("a");
return null;
}
}
My component class looks like:
#Component
public interface DataTransformerComponent {
DataHandler getHandler();
}
When i compile the above code it runs absolutely fine.
Now i want to make my A dependency #Singleton.
So i change my dependency class and component class as follows:
#Singleton
#Component
public interface DataTransformerComponent {
DataHandler getHandler();
}
Dependency class:
#Singleton
public class A {
#Inject
public A() {
}
public JSONObject executeTransformation(JSONObject jsonObject) {
System.out.println("a");
return null;
}
}
But now the generated component shows compilation errors saying:
A_Factory not found and it fails in the initialize() method.
DaggerDataTransformerComponent :
#Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class DaggerDataTransformerComponent implements DataTransformerComponent {
private Provider<A> aProvider;
private Provider<DataHandler> dataHandlerProvider;
private DaggerDataTransformerComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static DataTransformerComponent create() {
return builder().build();
}
#SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.aProvider = DoubleCheck.provider(A_Factory.create());
this.dataHandlerProvider = DataHandler_Factory.create(aProvider);
}
#Override
public DataHandler getHandler() {
return dataHandlerProvider.get();
}
public static final class Builder {
private Builder() {}
public DataTransformerComponent build() {
return new DaggerDataTransformerComponent(this);
}
}
}
I am unable to figure out why it does not create _factory class when i use #Singleton annotation.?.
Just use regular JavaScript + node.js, its a lot simpler

Whitelisting application properties in Spring Cloud Data Flow

When I create a custom app for SCDF I can, according to the reference define relevant properties that are visible through the dashboard when creating a new stream/task. I created a spring-configuration-metadata-whitelist.properties file like this:
configuration-properties.classes=com.example.MySourceProperties
configuration-properties.names=my.prop1,my.prop2
When I create a new stream definition through the dashboard all properties defined in com.example.MySourceProperties are displayed in the properties dialog, but my.prop1 and my.prop2 are not. Both properties aren't optional and must always be set by the user. How can I include them in the properties dialog?
This tells it which class to pull these properties from Task1 properties class
That we can use with "#EnableConfigurationProperties(Task1Properties.class) declaration
configuration-properties.classes=com.shifthunter.tasks.Task1Properties
Task1Properties.java
package com.shifthunter.tasks;
import org.springframework.boot.context.properties.ConfigurationProperties;
#ConfigurationProperties("pulldata-task")
public class Task1Properties {
/**
* The path to get the source doc from
*/
private String sourceFilePath;
/**
* The path to put the destination doc
*/
private String destinationFilePath;
/**
* Property to drive the exit code
*/
private String controlMessage;
public String getSourceFilePath() {
return sourceFilePath;
}
public void setSourceFilePath(String sourceFilePath) {
this.sourceFilePath = sourceFilePath;
}
public String getDestinationFilePath() {
return destinationFilePath;
}
public void setDestinationFilePath(String destinationFilePath) {
this.destinationFilePath = destinationFilePath;
}
public String getControlMessage() {
return controlMessage;
}
public void setControlMessage(String controlMessage) {
this.controlMessage = controlMessage;
}
}
ShiftHunterTaskPullDataApp.java
package com.shifthunter.tasks;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.task.configuration.EnableTask;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#EnableTask
#EnableConfigurationProperties(Task1Properties.class)
#SpringBootApplication
public class ShiftHunterTaskPullDataApp {
public static void main(String[] args) {
SpringApplication.run(ShiftHunterTaskPullDataApp.class, args);
}
#Bean
public Task1 task1() {
return new Task1();
}
public class Task1 implements CommandLineRunner {
#Autowired
private Task1Properties config;
#Override
public void run(String... strings) throws Exception {
System.out.println("source: " + config.getSourceFilePath());
System.out.println("destination: " + config.getDestinationFilePath());
System.out.println("control message: " + config.getControlMessage());
if(config.getControlMessage().equals("fail")) {
System.out.println("throwing an exception ...");
throw new Exception("I'm ANGRY");
}
System.out.println("pulldata-task complete!");
}
}
}
Sream Dataflow task-pull-data
app register --name task-pull-data --type task --uri maven://com.shifthunter.tasks:shifthunter-task-pulldata:jar:0.0.1-SNAPSHOT
task-pull-data - Details

EventBus in Reactor 3.x

I know that EventBus is deprecated in Reactor3.x, and the suggested solution is ReplayProcessor. I have read https://github.com/reactor/reactor-core/issues/375. But the code here is too draft. I created a demo project to prove the idea here. Can someone give some comments?
======== Application.java
package hello;
import org.reactivestreams.Subscription;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Flux;
import reactor.core.publisher.ReplayProcessor;
import reactor.core.publisher.BaseSubscriber;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application implements CommandLineRunner {
private static final int NUMBER_OF_QUOTES = 10;
#Bean
ReplayProcessor createReplayProcessor() {
ReplayProcessor<MyEvent> rp = ReplayProcessor.create();
Flux<MyEvent> interest1 = rp.filter(ev -> filterInterest1(ev));
Flux<MyEvent> interest2 = rp.filter(ev -> filterInterest2(ev));
interest1.subscribe(new BaseSubscriber<MyEvent>() {
#Override
protected void hookOnSubscribe(Subscription subscription) {
requestUnbounded();
}
#Override
protected void hookOnNext(MyEvent value) {
//todo: call service method
System.out.println("event 1 handler -> event name:" + value.getEventName());
}
});
interest2.subscribe(new BaseSubscriber<MyEvent>() {
#Override
protected void hookOnSubscribe(Subscription subscription) {
requestUnbounded();
}
#Override
protected void hookOnNext(MyEvent value) {
//todo: call service method
System.out.println("event2 handler -> event name:" + value.getEventName());
}
});
return rp;
}
public boolean filterInterest1(MyEvent myEvent) {
if (myEvent != null && myEvent.getEventName() != null
&& myEvent.getEventName().equalsIgnoreCase("event1")) {
return true;
}
return false;
}
public boolean filterInterest2(MyEvent myEvent) {
if (myEvent != null && myEvent.getEventName() != null
&& myEvent.getEventName().equalsIgnoreCase("event2")) {
return true;
}
return false;
}
#Autowired
private Publisher publisher;
#Bean
public CountDownLatch latch() {
return new CountDownLatch(NUMBER_OF_QUOTES);
}
#Override
public void run(String... args) throws Exception {
publisher.publishQuotes(NUMBER_OF_QUOTES);
}
public static void main(String[] args) throws InterruptedException {
ApplicationContext app = SpringApplication.run(Application.class, args);
app.getBean(CountDownLatch.class).await(10, TimeUnit.SECONDS);
}
}
==========MyEvent.java=============
package hello;
public class MyEvent {
private String eventName = "";
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
public MyEvent(String eventName) {
this.eventName = eventName;
}
public void filterInterest1(MyEvent myEvent) {
}
}
=============Publisher.java ===========
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.ReplayProcessor;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
#Service
public class Publisher {
#Autowired
ReplayProcessor rp;
#Autowired
CountDownLatch latch;
public void publishQuotes(int numberOfQuotes) throws InterruptedException {
long start = System.currentTimeMillis();
rp.onNext(new MyEvent("event1"));
rp.onNext(new MyEvent("event2"));
rp.onNext(new MyEvent("event3"));
long elapsed = System.currentTimeMillis() - start;
System.out.println("Elapsed time: " + elapsed + "ms");
System.out.println("Average time per quote: " + elapsed / numberOfQuotes + "ms");
}
}
The whole code is https://github.com/yigubigu/reactor-start-sample.git
IMHO you can relay in Spring event handlers. Matt Raible and Josh Long use that in this couple of tutorials:
https://developer.okta.com/blog/2018/09/24/reactive-apis-with-spring-webflux
https://developer.okta.com/blog/2018/09/25/spring-webflux-websockets-react
Key takeaways:
#Component
class ProfileCreatedEventPublisher implements
ApplicationListener<ProfileCreatedEvent>,
Consumer<FluxSink<ProfileCreatedEvent>>
Uses an event loop to take events from a LinkedBlockingQueue.
#Override
public void onApplicationEvent(ProfileCreatedEvent event)
Queue the events that can be published anywhere within your app.
ProfileCreatedEventPublisher is used in ServerSentEventController to create a Flux of events (that can be chained with a filter), it transforms and sends them to a web client.

extension function using saxon s9api

I am trying to add an extension function, but is failing with :
Caused by: net.sf.saxon.trans.XPathException: Unknown system function follow()
at net.sf.saxon.expr.parser.XPathParser.grumble(XPathParser.java:282)
I see (in debug) that function registered with the integrated library. I was expecting saxon to look for the function in the integrated library but it is searching in system functions and throwing error. What is causing this function to be represented as a system function.
I am using the following :
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>9.7.0-14</version>
</dependency>
Thank you
my code is
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.lib.ExtensionFunctionCall;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XPathExecutable;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.SequenceType;
public class FollowTest {
public static void main(String[] args) throws Exception {
new FollowTest().test();
}
private void test () throws Exception {
Processor proc = new Processor(false);
proc.registerExtensionFunction(new Follow());
XPathCompiler xx = proc.newXPathCompiler();
XPathExecutable x = xx.compile("follow(/a/b/c)/type='xyz'");
}
public class Follow extends ExtensionFunctionDefinition {
#Override
public StructuredQName getFunctionQName() {
return new StructuredQName("", "http://example.com/saxon-extension", "follow");
}
#Override
public int getMinimumNumberOfArguments() {
return 1;
}
#Override
public int getMaximumNumberOfArguments() {
return 1;
}
#Override
public SequenceType[] getArgumentTypes() {
return new net.sf.saxon.value.SequenceType[] {SequenceType.SINGLE_STRING,};
}
#Override
public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
return SequenceType.NODE_SEQUENCE;
}
#Override
public boolean trustResultType() {
return true;
}
#Override
public boolean dependsOnFocus() {
return false;
}
#Override
public boolean hasSideEffects() {
return false;
}
#Override
public ExtensionFunctionCall makeCallExpression() {
return null;
}
private class followCall extends ExtensionFunctionCall {
#Override
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
return null;
}
}
}
}
In the XPath expression you have written
follow(/a/b/c)
A function name with no namespace prefix is assumed to be in the default namespace for functions, which by default is the system function namespace http://www.w3.org/2005/xpath-functions. You need to use a prefix that's bound to the URI appearing in the extension function definition, namely http://example.com/saxon-extension

How to inject a bean into custom argument resolver?

Hello i use spring boot 1.3.2 version. I have a custom argument resolver which's name is ActiveCustomerArgumentResolver. Everything is great, resolveArgument method works fine but i can't initialize my service component which is of my custom arg. resolver. Is there a problem with lifecycle process? Here is my code:
import org.springframework.beans.factory.annotation.Autowired;
//other import statements
public class ActiveCustomerArgumentResolver implements HandlerMethodArgumentResolver {
#Autowired
private CustomerService customerService;
#Override
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.hasParameterAnnotation(ActiveCustomer.class) && parameter.getParameterType().equals(Customer.class))
return true;
else
return false;
}
#Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Principal userPrincipal = webRequest.getUserPrincipal();
if (userPrincipal != null) {
Long customerId = Long.parseLong(userPrincipal.getName());
return customerService.getCustomerById(customerId).orNull(); //customerService is still NULL here, it keeps me getting NullPointerEx.
} else {
throw new IllegalArgumentException("No user principal is associated with the current request, yet parameter is annotated with #ActiveUser");
}
}
}
Let the Spring create the resolver for you by making it a Component:
#Component
public class ActiveCustomerArgumentResolver implements HandlerMethodArgumentResolver {...}
Then inject the resolver into your WebConfig instead of simply using the new, like following:
#EnableWebMvc
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired private ActiveCustomerArgumentResolver activeCustomerArgumentResolver;
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(activeCustomerArgumentResolver);
}
}
This is how i've solved the problem, not a generic one but helps me a lot:
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application extends WebMvcConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(activeCustomerArgumentResolver());
}
#Bean
public ActiveCustomerArgumentResolver activeCustomerArgumentResolver() {
return new ActiveCustomerArgumentResolver();
}
}

Resources