In a setup as described in the docs:
public class MyWireMockResource implements QuarkusTestResourceLifecycleManager {
WireMockServer wireMockServer;
#Override
public Map<String, String> start() {
wireMockServer = new WireMockServer(8090);
wireMockServer.start();
// create some stubs
return Map.of("some.service.url", "localhost:" + wireMockServer.port());
}
//...
}
How can I access the value returned in in the start() method.
The javadoc says:
A map of system properties that should be set for the running test
Why "should be"?
I would like to set some values that I can later used in my productive code.
I have tried: System.getProperty("some.service.url")
I have also tried:
#ConfigProperty(name = "some.service.url")
String serviceUrl;
But the value is not set.
Any help is appreciated.
The system properties mentioned in the javadoc is confusing. The returned map will as expected override the configurations.
It was not working for me to access it with the #ConfigProperty annotation because I was reading the value in the constructor and not in the method annotated with #PostConstruct.
#ApplicationScoped
public class SomeBean {
#ConfigProperty(name = "some.service.url")
String serviceUrl;
public SomeBean() {
// we are too early here, value is null:
System.out.println("value in constructor: " + serviceUrl);
}
#PostConstruct
void init() {
System.out.println("value in init: " + serviceUrl);
}
}
Related
Below is the method I'm trying to write unit test using junit 5
#Value("${proxy.host}")
private String endpoint;
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
Below is the unit test I'm trying to run
#InjectMocks
private AWSAuthHandler testAWSAuthHandler;
#Test
public void testSetAwsRequestGETParameter() throws Exception {
URI mockedURI = Mockito.mock(URI.class);
assertNotNull(testAWSAuthHandler.setAwsRequestGETParameter("/status/7deaed5e-3080-45ec-89ba-403977d60c0c"));
}
Below is the stack trace:
java.lang.NullPointerException
at java.base/java.net.URI$Parser.parse(URI.java:3106)
at java.base/java.net.URI.<init>(URI.java:600)
at java.base/java.net.URI.create(URI.java:881)
Can someone please help me with the missing part? Thank you
For setting properties of class that you can't mock you can use Spring Reflection Utils, like that:
ReflectionUtils.setField(field, target, value);
where the field is the name of the field which you want to set ("endpoint" for your case),
target is the mocked class (testAWSAuthHandler for your case)
value is the wanted value
As Sweta Sharma said, you need to initialise AWSAuthHandler with some value for endpoint field. That's why it is better to use constructor injection rather than field one.
Assuming your AWSAuthHandler class look like this (as you didn't provide the code for the whole class):
public class AWSAuthHandler {
#Value("${proxy.host}")
private String endpoint;
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
You can refactor it in the following way:
public class AWSAuthHandler {
private String endpoint;
public AWSAuthHandler(#Value("${proxy.host}") String endpoint) {
this.endpoint = endpoint;
}
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
Then you can create tests for this class:
private AWSAuthHandler testAWSAuthHandler;
#BeforeEach
void setUpTests() {
this.testAWSAuthHandler = new AWSAuthHandler("some-endpoint-here");
}
#Test
public void testSetAwsRequestGETParameter() throws Exception {
assertNotNull(testAWSAuthHandler.setAwsRequestGETParameter("/status/7deaed5e-3080-45ec-89ba-403977d60c0c"));
}
You can read more about Spring #Value annotation here, for example: https://www.baeldung.com/spring-value-annotation
I'm trying to set up a micronaut service with a Consul configuration. When the service starts it successfully initializes the property of the bean with the value provided from the key-value store. However it doesn't reload when the value changes, even if the refresh is triggered manually.
Here's the bean:
#Refreshable
public class ConfigBean {
#Property(name = "welcome-message")
private String message = "doe!";
#PostConstruct
public void init() {
String text = this + "Scattered Clouds " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd/MMM/yy HH:mm.ss.SSS"));
System.out.println(text + "\r\n" + this.message);
}
}
And here is the simple controller endpoint:
#Controller("/p")
public class Controller {
#Inject
ApplicationContext applicationContext;
#Inject
private ConfigBean config;
#Get("/r")
#Produces(MediaType.TEXT_PLAIN)
public String refresh() {
applicationContext.publishEvent(new RefreshEvent());
return "Hello World";
}
#Get("/m")
#Produces(MediaType.TEXT_PLAIN)
public String message() {
return config.getMessage();
}
}
With this code what happens is
value is successfully resolved from config store and shown when navigating to localhost:8080/p/m
when getting localhost:8080/p/r for manual refresh interestingly enough the init() method of the config bean is called but the value in the message attribute is not updated
What is needed to re-trigger the update of the bean? Is there maybe an implicit call that can be used to purge a config-cache so it is fetched again?
The documentation is a bit sparse about this (Version 2.2.0 was used), thanks in advance!
I am using below annotations in my config class to get the values from properties file(yml).
Configuration
EnableConfigurationProperties
ConfigurationProperties (prefix = "notification")
I am able to get the values inside public methods without problem using the class . But I am getting 'Error Creating bean' Error when I try to assign value instance variable of the class using config class.
Below is my code. Can someone please throw some light.
This is my config class
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties (prefix = "notification")
public class NotifyYaml {
private String subscriptionId;
public String getSubscriptionId() {
return subscriptionId;
}
public void setSubscriptionId(String subscriptionId) {
this.subscriptionId = subscriptionId;
}
Below is the class where I am getting error during startup.
#Component
public class PubSubController {
#Autowired
private NotifyYaml notify;
public PubSubController() {
// TODO Auto-generated constructor stub
}
String projectId = "ccc-g-pre-proj-cacdate";
//Error in this line
String subscriptionId = notify.getSubscriptionId();
The #Autowired object only gets filled in after the object is created.
This means that while the object is being created, it tries to call a method from a null object.
I would suggest using something like a #PostConstruct method. (Note: you will need to include javax.annotations into your project somehow.)
String subscriptions; // remove the value for now...
#PostConstruct
private void init() {
subscriptions = notify.getSubscriptionId(); // ...and add it back in here.
}
I have a resource in my Jersey REST api that has a private instance variable:
#Path("test")
public class TestResource implements ServletContextListener
{
private String someString;
#GET
public void test()
{
System.out.println("someString " + someString);
}
#Override
public void contextDestroyed(ServletContextEvent ctxt) {
System.out.println("Destroying context");
}
#Override
public void contextInitialized(ServletContextEvent ctxt) {
System.out.println("TestResource initialized!");
someString = "SET";
System.out.println("someString has been set. someString: " + someString);
}
}
On server startup/restart the instance variable someString is initialized during contextInitialized() and is correctly printed out. However when I set a GET request to http://localhost:8080/myapp/api/test (i.e. invoke the test() method above) the variable someString is null.
How can I prevent that?
From the JAX-RS specification:
By default a new resource class instance is created for each request to that resource.
So, any state you set on your resource class instance is meaningless, since the instance is never used again. If you want to persist a value, place it in the ServletContext’s attributes:
// All classes in the web app share a ServletContext, so attribute names
// need to start with package names to prevent collisions.
private static final String SOME_ATTRIBUTE = TestResource.class.getName() + ".someAttribute";
#Override
public void contextInitialized(ServletContextEvent ctxt) {
System.out.println("TestResource initialized!");
String someString = "SET";
System.out.println("someString has been set. someString: " + someString);
ctxt.getServletContext().setAttribute(SOME_ATTRIBUTE, someString);
}
#GET
public void test(#Context ServletContext context) {
System.out.println("someString " + context.getAttribute(SOME_ATTRIBUTE));
}
Storing values in static fields will require you to implement thread safety and will not work in a distributed production environment.
I believe this should be a comment but I don't have enough reputation. So I am writing as an answer.
This question gives an example for #Singleton annotation. It provides a cleaner approach.
I am using spring MVC. From my controller, I am calling jobLauncher and in jobLauncher I am passing job parameters like below and I'm using annotations to enable configuration as below:
#Configuration
#EnableBatchProcessing
public class BatchConfiguration {
// read, write ,process and invoke job
}
JobParameters jobParameters = new JobParametersBuilder().addString("fileName", "xxxx.txt").toJobParameters();
stasrtjob = jobLauncher.run(job, jobParameters);
and here is my itemprocessor
public class DataItemProcessor implements ItemProcessor<InputData, OutPutData> {
public OutPutData process(final InputData inputData) throws Exception {
// i want to get job Parameters here ????
}
}
1) Put a scope annotation on your data processor i.e.
#Scope(value = "step")
2) Make a class instance in your data processor and inject the job parameter value by using value annotation :
#Value("#{jobParameters['fileName']}")
private String fileName;
Your final Data processor class will look like:
#Scope(value = "step")
public class DataItemProcessor implements ItemProcessor<InputData, OutPutData> {
#Value("#{jobParameters['fileName']}")
private String fileName;
public OutPutData process(final InputData inputData) throws Exception {
// i want to get job Parameters here ????
System.out.println("Job parameter:"+fileName);
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
In case your data processor is not initialized as a bean, put a #Component annotation on it:
#Component("dataItemProcessor")
#Scope(value = "step")
public class DataItemProcessor implements ItemProcessor<InputData, OutPutData> {
A better solution (in my opinion) that avoids using Spring's hacky expression language (SpEL) is to autowire the StepExecution context into your processor using #BeforeStep.
In your processor, add something like:
#BeforeStep
public void beforeStep(final StepExecution stepExecution) {
JobParameters jobParameters = stepExecution.getJobParameters();
// Do stuff with job parameters, e.g. set class-scoped variables, etc.
}
The #BeforeStep annotation
Marks a method to be called before a Step is executed, which comes
after a StepExecution is created and persisted, but before the first
item is read.
I have written the in the process itself, rather then creating separate file using the lambda expression.
#Bean
#StepScope
public ItemProcessor<SampleTable, SampleTable> processor(#Value("#{jobParameters['eventName']}") String eventName) {
//return new RandomNumberProcessor();
return item -> {
SampleTable dataSample = new SampleTable();
if(data.contains(item)) {
return null;
}
else {
dataSample.setMobileNo(item.getMobileNo());
dataSample.setEventId(eventName);
return dataSample;
}
};
}