#Value returning null in unit test - java

I have a spring boot app with an Endpoint Test Configuration class and a unit test to test my http client. I am trying to get my server address and port from my application.properties which is located in my src/test.(All the classes are in my src/test.)
Here is my config class code :
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import javax.xml.bind.JAXBException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import com.nulogix.billing.service.PredictionEngineService;
import com.nulogix.billing.ws.endpoint.AnalyzeEndPoint;
import com.nulogix.billing.ws.endpoint.GetVersionEndPoint;
#Configuration
public class EndPointTestConfiguration {
#Value("${billing.engine.address}")
private String mockAddress;
#Value("${billing.engine.port}")
private String mockPort;
#Bean
public String getAddress() {
String serverAddress = "http://" + mockAddress + ":" + mockPort;
return serverAddress;
}
#Bean
public GetVersionEndPoint getVersionEndPoint() {
return new GetVersionEndPoint();
}
I annotated the values from my .properties with #value and then created a method that I instantiated with a bean to to return my server address string.
I then use that string value here in my HttpClientTest class:
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Map;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ConfigurableApplicationContext;
import com.google.gson.Gson;
import com.nulogix.billing.configuration.EndPointTestConfiguration;
import com.nulogix.billing.mockserver.MockServerApp;
#SpringBootTest(classes = EndPointTestConfiguration.class)
public class HttpClientTest {
#Autowired
EndPointTestConfiguration endpoint;
public static final String request_bad = "ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|";
public static final String request_good = "ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|-123|-123|-123|0.0|0.0|0.0|0.0|0.0|0.0|0.0";
//gets application context
static ConfigurableApplicationContext context;
//call mock server before class
#BeforeClass
static public void setup(){
SpringApplication springApplication = new SpringApplicationBuilder()
.sources(MockServerApp.class)
.build();
context = springApplication.run();
}
//shutdown mock server after class
#AfterClass
static public void tearDown(){
SpringApplication.exit(context);
}
#Test
public void test_bad() throws ClientProtocolException, IOException {
// missing parameter
String result = Request.Post(endpoint.getAddress())
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(request_bad, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
Map<?, ?> resultJsonObj = new Gson().fromJson(result, Map.class);
// ensure the key exists
assertEquals(resultJsonObj.containsKey("status"), true);
assertEquals(resultJsonObj.containsKey("errorMessage"), true);
// validate values
Boolean status = (Boolean) resultJsonObj.get("status");
assertEquals(status, false);
String errorMessage = (String) resultJsonObj.get("errorMessage");
assertEquals(errorMessage.contains("Payload has incorrect amount of parts"), true);
}
#Test
public void test_good() throws ClientProtocolException, IOException {
String result = Request.Post(endpoint.getAddress())
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(request_good, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
Map<?, ?> resultJsonObj = new Gson().fromJson(result, Map.class);
// ensure the key exists
assertEquals(resultJsonObj.containsKey("status"), true);
assertEquals(resultJsonObj.containsKey("errorMessage"), false);
assertEquals(resultJsonObj.containsKey("HasCopay"), true);
assertEquals(resultJsonObj.containsKey("CopayAmount"), true);
assertEquals(resultJsonObj.containsKey("HasCoinsurance"), true);
assertEquals(resultJsonObj.containsKey("CoinsuranceAmount"), true);
assertEquals(resultJsonObj.containsKey("version"), true);
// validate values
Boolean status = (Boolean) resultJsonObj.get("status");
assertEquals(status, true);
String version = (String) resultJsonObj.get("version");
assertEquals(version, "0.97");
}
}
I use it in the request.post, I didn't want to hardcode in my IP address and port number.
When I run the test it says
[ERROR] HttpClientTest.test_bad:63 NullPointer
[ERROR] HttpClientTest.test_good:86 NullPointer
But I am not sure why it is null? I am pretty sure I have everything instantiated and the string is clearly populated..
My package structure for my config is com.billing.mockserver and my package structure for my unit test is com.billing.ws.endpoint.
Here is my application.properties
server.port=9119
server.ssl.enabled=false
logging.config=classpath:logback-spring.xml
logging.file=messages
logging.file.max-size=50MB
logging.level.com.nulogix=DEBUG
billing.engine.address=127.0.0.1
billing.engine.port=9119
billing.engine.api.version=0.97
billing.engine.core.name=Patient_Responsibility

You are missing springboot basic understanding. #Configuration class is to initialize other spring beans and other things and are the first classes which get initialized. You should not #Autowire #configuration class.
In your Configuration class you can either create Spring bean for username and password and autowire that in your test class or directly use #Value in your Test class.
Example: in your configuration class you are creating bean of GetVersionEndPoint and you can autowire that in your Test class.
Update 2:
For test classes, you need to add application.properties file in src\test\resource

Related

Apache camel - I want to send to my mock endpoint

I have this test class - currently it is checking the response at the endpoint
Endpoints.SEDA_PROCESS_ENDPOINT
but I need it to check at
"mock:"+Endpoints.SEDA_PROCESS_ENDPOINT
Is there a way to forward the response to this mock endpoint I have just defined?
below is my test class
package com.sams.pricing.prism.data.processor;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import org.apache.camel.EndpointInject;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.spring.MockEndpoints;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.sams.pricing.prism.data.processor.model.CostIQRetail;
import com.sams.pricing.prism.data.processor.routes.PrismRouter;
import com.sams.pricing.prism.data.processor.service.RulesEngineClient;
import com.sams.pricing.prism.data.processor.util.Endpoints;
#SpringBootTest
#CamelSpringBootTest
#MockEndpoints( Endpoints.SEDA_PROCESS_ENDPOINT)
public class CamelRouteTests3 {
#Autowired
private ProducerTemplate template;
#EndpointInject( "mock:" + Endpoints.SEDA_PROCESS_ENDPOINT)
private MockEndpoint mock;
#Mock
private PrismRouter p;
#Mock
private RulesEngineClient rulesEngineClientMock;
public CostIQRetail costIQObject() {
CostIQRetail obj = new CostIQRetail();
obj.setItemNbr(123);
obj.setLocationNbr(4931);
obj.setIsDcFlag(false) ;
obj.setStatus("SUCCESS");
obj.setOrderableCost(new BigDecimal((10.0)));
obj.setWarehousePackCost(new BigDecimal(100.0));
obj.setOrderablePrepaidCost(null) ;
obj.setOrderableCollectCost(null) ;
obj.setReasonCode("Markdown - category funded");
obj.setEffectiveDate("2022-12-29");
obj.setIsFutureEffectiveDate(false);
obj.setCostType("WAREHOUSE PACK COST");
obj.setSource("COST IQ");
obj.setCreatedBy("lab1 account");
obj.setCreatedByUserId("LB-cost-test");
obj.setCreatedTs("2022-12-29T02:42:25.529Z");
obj.setCurrentRetailPrice(new BigDecimal(55.0)) ;
obj.setCurrentOrderableCost(null);
obj.setCurrentWarehousePackCost(new BigDecimal((0.0)));
obj.setCurrentOrderablePrepaidCost(null) ;
obj.setCurrentOrderableCollectCost(null);
obj.setMarginChange(new BigDecimal((-100.0)));
obj.setOwedToClub(new BigDecimal((0.0)));
obj.setItemSourceId(3572924);
obj.setPriceDestId(701800);
obj.setCategory(87);
obj.setOrderableQty(null);
obj.setOldMargin(new BigDecimal((100.0)));
obj.setNewMargin(new BigDecimal(0.0));
return obj;
}
private String costIQPayloadString() throws JsonProcessingException
{
String key = "{\"retailTypeReasonCode\":{\"retailTypeReasonCodeId\":{\"retailType\":\"BP\",\"retailReasonCode\":\"CC\"}},\"expirationDate\":null,\"customerRetailAmount\":0.0,\"auditMessage\":null,\"createdTimestamp\":null,\"clientID\":\"COST IQ\",\"rowNumber\":0,\"auditRecordTimestamp\":null,\"clubNumber\":4931,\"itemNumber\":123,\"effectiveDate\":\"2022-12-29\",\"submissionID\":null,\"retailAmount\":55.0,\"createdBy\":\"lab1 account\"}";
String key2 = "{\"retailTypeReasonCode\":{\"retailTypeReasonCodeId\":{\"retailType\":\"BP\",\"retailReasonCode\":\"CC\"}},\"expirationDate\":null,\"customerRetailAmount\":0.0,\"auditMessage\":null,\"createdTimestamp\":null,\"clientID\":\"COST IQ\",\"rowNumber\":0,\"auditRecordTimestamp\":null,\"categoryId\":87,\"subCategoryId\":1,\"clubNumber\":4931,\"itemNumber\":123,\"effectiveDate\":\"2022-12-29\",\"submissionID\":null,\"retailAmount\":10.0,\"createdBy\":\"lab1 account\"}";
return key2;
}
#Test
void test() throws Exception {
// Set up the mock endpoints
mock.expectedBodiesReceived(costIQPayloadString());
//p.interceptSendToEndpoint( Endpoints.SEDA_PROCESS_ENDPOINT).to(mock.getEndpointUri());
Mockito.when(rulesEngineClientMock.validateRules((costIQObject()))).thenReturn(costIQObject()); //.thenR
Map<String, Object> headers = new HashMap<>();
headers.put("appName", "costIQ");
// Send the test message to the SEDA_SEND_ENDPOINT
template.sendBodyAndHeaders(Endpoints.SEDA_SEND_ENDPOINT, costIQObject(), headers);
mock.assertIsSatisfied();
}
}
I have looked at advice with but that involves adding in the cameltestsupport and would need to re-write this code. Is there a way to do this with current implementations?

Wiremock verify doesn't work if run together with other integration tests

I'm not an expert with Wiremock and probably there's something wrong in my settings/configuration but I'm facing a weird scenario when it comes to verify a specific test.
if I run this specific test among the whole IT suite, the test fails on WireMockServer.verify(int count, RequestPatternBuilder requestPatternBuilder) but if I run the test alone, it works fine and the assertion is correct.
so what I did so far to understand this weird behavior is :
I set a break point the check if the actualCount inside the method was correct and indeed it is (only if run alone).
more over, I actually put some log messages to verify on the application side that this method has been invoked 4 times (one is the first request which throws exception and the other 3 are the so called retries)
I've debugged this specific use case by sending some requests with postman and the behaviour is what I expected
so at the moment I got no clue about what the heck is going on with this specific test when is running among the whole IT suite.
any input about what could it be the issue or why Wiremock behaves in this specific way?
Thank you in advance for the help & inputs :)
I have the same issue: tests finish successfully if I run them separately and fail when run with a class.
Wiremock version "com.github.tomakehurst:wiremock-jre8:2.33.1"
package com.kn.tic.web.client.jira;
import com.atlassian.jira.rest.client.api.domain.input.IssueInput;
import com.atlassian.jira.rest.client.api.domain.input.IssueInputBuilder;
import com.atlassian.jira.rest.client.api.domain.util.UriUtil;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.kn.tic.config.ApplicationProperties;
import org.apache.http.HttpStatus;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.data.util.Pair;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.UUID;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
class CustomAsynchronousIssueRestClientTest {
private static final String USER = "user";
private static final String PASS = "pass";
private static final String HOST = "localhost";
private static final String PROTOCOL = "http";
private static final String JIRA_TRACKING_ID = "jiraTrackingId";
#TempDir
Path tempDir;
private final WireMockServer wireMockServer = new WireMockServer();
private JiraClient jiraClient;
#BeforeEach
public void setUp() {
this.wireMockServer.start();
ApplicationProperties applicationProperties = new ApplicationProperties();
applicationProperties.getJira().setUsername(USER);
applicationProperties.getJira().setPassword(PASS);
applicationProperties.getJira().setHost(HOST);
applicationProperties.getJira().setProtocol(PROTOCOL);
applicationProperties.getJira().setPort(wireMockServer.port());
this.jiraClient = new JiraClient(applicationProperties.getJira());
}
#AfterEach
void afterAll() {
this.wireMockServer.stop();
}
#Test
void testThatCustomCreateIssueImplementationAddsJiraTrackingIdToQuery() {
String jiraTrackingId = UUID.randomUUID().toString();
String uriPath = "/rest/api/latest/issue";
wireMockServer.stubFor(post(urlPathEqualTo(uriPath))
.withQueryParam(JIRA_TRACKING_ID, equalTo(jiraTrackingId))
.withHeader(HttpHeaders.CONTENT_TYPE, containing(MediaType.APPLICATION_JSON_VALUE))
.withBasicAuth(USER, PASS)
.willReturn(
aResponse()
.withStatus(HttpStatus.SC_OK)
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.withBody("{\"id\":\"2197656\",\"key\":\"TTT-822\",\"self\":\"https://test-jira.com/rest/api/latest/issue/2197656\"}")
));
IssueInput issueInput = new IssueInputBuilder()
.setProjectKey("TCF")
.setIssueTypeId(5L)
.setSummary("summary")
.setReporterName("reporter")
.setDescription("description")
.build();
jiraClient.createIssue(issueInput, jiraTrackingId);
verify(postRequestedFor(urlPathEqualTo(uriPath))
.withQueryParam(JIRA_TRACKING_ID, equalTo(jiraTrackingId))
.withHeader(HttpHeaders.CONTENT_TYPE, containing(MediaType.APPLICATION_JSON_VALUE)));
}
#Test
void testThatCustomAddAttachmentImplementationAddsJiraTrackingIdToQuery() throws URISyntaxException, IOException {
String jiraTrackingId = UUID.randomUUID().toString();
URI issueUri = new URI(String.format("%s://%s:%s/rest/api/latest/issue/2197654",PROTOCOL, HOST, wireMockServer.port()));
URI attachmentUri = UriUtil.path(issueUri, "attachments");
wireMockServer.stubFor(post(urlPathEqualTo(attachmentUri.getPath()))
.withQueryParam(JIRA_TRACKING_ID, equalTo(jiraTrackingId))
.withHeader(HttpHeaders.CONTENT_TYPE, containing(MediaType.MULTIPART_FORM_DATA_VALUE))
.withBasicAuth(USER, PASS)
.willReturn(
aResponse()
.withStatus(HttpStatus.SC_OK)
));
Path tempFile = Files.createFile(tempDir.resolve("attachment.pdf"));
Files.writeString(tempFile, "test");
List<Pair<File, String>> attachments = List.of(Pair.of(tempFile.toFile(), "attachment.pdf"));
jiraClient.addAttachmentsToIssue(issueUri, attachments, jiraTrackingId);
verify(postRequestedFor(urlPathEqualTo(attachmentUri.getPath()))
.withQueryParam(JIRA_TRACKING_ID, equalTo(jiraTrackingId))
.withHeader(HttpHeaders.CONTENT_TYPE, containing(MediaType.MULTIPART_FORM_DATA_VALUE)));
}
}

Apache kafka embedded kafka junit test - application starting when I run unit test

I am developing an asynchronous mail server in spring boot using kafka.
I have written tests with embedded kafka which starts its own kafka topic in a random port and use it for testing.
When I started this application context is loading and its expecting for kafka cluster in my local. I need to stop application conext from loading.
I replicated the code from https://github.com/code-not-found/spring-kafka/blob/master/spring-kafka-unit-test-classrule/src/test/java/com/codenotfound/kafka/producer/SpringKafkaSenderTest.java which works absolutely fine. When I followed same style in my project, I can see actual apllication starting.
SpringKafkaSenderTest .java
package com.mailer.embeddedkafkatests;
import static org.junit.Assert.assertTrue;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.listener.ContainerProperties;
import org.springframework.kafka.listener.KafkaMessageListenerContainer;
import org.springframework.kafka.listener.MessageListener;
import org.springframework.kafka.test.rule.EmbeddedKafkaRule;
import org.springframework.kafka.test.utils.ContainerTestUtils;
import org.springframework.kafka.test.utils.KafkaTestUtils;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import com.mailer.model.Mail;
import com.mailer.producer.KafkaMessageProducer;
import com.mailer.serializer.MailSerializer;
#RunWith(SpringRunner.class)
#SpringBootTest
#DirtiesContext
public class SpringKafkaSenderTest {
private static final Logger LOGGER =
LoggerFactory.getLogger(SpringKafkaSenderTest.class);
private static String SENDER_TOPIC = "sender.t";
#Autowired
private KafkaMessageProducer sender;
private KafkaMessageListenerContainer<String, Mail> container;
private BlockingQueue<ConsumerRecord<String, Mail>> records;
#ClassRule
public static EmbeddedKafkaRule embeddedKafka =
new EmbeddedKafkaRule(1, true, SENDER_TOPIC);
#Before
public void setUp() throws Exception {
// set up the Kafka consumer properties
Map<String, Object> consumerProperties =
KafkaTestUtils.consumerProps("sender", "false",
embeddedKafka.getEmbeddedKafka());
consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, MailSerializer.class);
// create a Kafka consumer factory
DefaultKafkaConsumerFactory<String, Mail> consumerFactory =
new DefaultKafkaConsumerFactory<String, Mail>(
consumerProperties);//, new StringDeserializer(), new JsonDeserializer<>(Mail.class));
// set the topic that needs to be consumed
ContainerProperties containerProperties =
new ContainerProperties(SENDER_TOPIC);
// create a Kafka MessageListenerContainer
container = new KafkaMessageListenerContainer<>(consumerFactory,
containerProperties);
// create a thread safe queue to store the received message
records = new LinkedBlockingQueue<>();
// setup a Kafka message listener
container
.setupMessageListener(new MessageListener<String, Mail>() {
#Override
public void onMessage(
ConsumerRecord<String, Mail> record) {
LOGGER.debug("test-listener received message='{}'",
record.toString());
records.add(record);
}
});
// start the container and underlying message listener
container.start();
// wait until the container has the required number of assigned partitions
ContainerTestUtils.waitForAssignment(container,
embeddedKafka.getEmbeddedKafka().getPartitionsPerTopic());
}
#After
public void tearDown() {
// stop the container
container.stop();
}
#Test
public void testSend() throws InterruptedException {
// send the message
Mail mail = new Mail();
mail.setFrom("vinoth#local.com");
sender.sendMessage(mail);
Thread.sleep(4000);
// check that the message was received
ConsumerRecord<String, Mail> received =
records.poll(10, TimeUnit.SECONDS);
// Hamcrest Matchers to check the value
assertTrue(received.value().getFrom().equals(mail.getFrom()));
System.out.println(received.value().getFrom());
// assertThat(received, hasValue(mail));
// AssertJ Condition to check the key
// assertThat(received).has(key(null));
}
}
Why would you like to stop the spring context from loading? Isn't the purpose of this junit to test your spring application?
In any case just remove the #SpringBootTest annotation and the spring context will not load.

Proper way to mock MIMEMessage?

I want to actually verify the fields set on the message, like the body, subject, from, etc… I’ve tried doing an argument captor as well which didn’t work and when I debug the code, the message is always showing null fields when it gets the javaMailSender.send(message) line.
Are there best practices in mocking MIMEMessage?
//EmailService.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
#Slf4j
public class EmailService {
private JavaMailSender javaMailSender;
#Autowired
public EmailService(JavaMailSender javaMailSender) {
this.javaMailSender = javaMailSender;
}
public void sendEmail() {
MimeMessage message = javaMailSender.createMimeMessage();
String body = "<html>\n" +
"<p> This the body </p>\n" +
"<br>\n";
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
mimeMessageHelper.setSubject("subject");
mimeMessageHelper.setTo("stack#overflow.com");
mimeMessageHelper.setFrom("overflow#stack.com");
mimeMessageHelper.setText(body, true);
javaMailSender.send(message);
} catch (MessagingException e) {
log.error("error");
}`enter code here`
}
}
Below is the test
//EmailServiceTest.java
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.springframework.mail.javamail.JavaMailSender;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
public class EmailServiceTest {
private EmailService emailService;
#Mock
private JavaMailSender javaMailSender;
#Mock
private MimeMessage message;
#Before
public void setUp() throws IOException {
initMocks(this);
emailService = new EmailService(javaMailSender);
}
#Test
public void sendEmail_sendsEmailWithCorrectContent() throws MessagingException {
ArgumentCaptor<MimeMessage> mimeMessageArgumentCaptor = ArgumentCaptor.forClass(MimeMessage.class);
when(javaMailSender.createMimeMessage()).thenReturn(message);
doNothing().when(javaMailSender).send(message);
emailService.sendEmail();
verify(javaMailSender, times(1)).send((mimeMessageArgumentCaptor.capture()));
assertEquals("subject", mimeMessageArgumentCaptor.getValue().getSubject());
}
}
It's generally easier to do this kind of testing using an integration test. Emails are often built using a template library such as freemarker, so an integration test is valuable in being able to verify that your template is correct as well.
You could do unit testing by using PowerMock to create a mock MimeMessageHelper, but PowerMock can sometimes be slow at keeping up with changes to other testing libraries, and such tests often end up brittle and of little value. For example, you could verify that setSubject() was called on mimeMessageHelper, but does that produce the outcome that you really want to test (that the subject is set on message)?

AttributeNotFoundException through JMX in Startup bean on Wildfly

Hello everyone!
I'm trying to load wildfly server's system properties through JMX in Startup bean's #PostConstruct method. It works fine on the already started server instance when deployment starts, but fails while starting with server instance bootstrapping.
Wildfly 11.0.0.CR1
Startup bean code:
package ru.wildfly.test.ejb.wildflyconsulregistrar.startup;
import ru.wildfly.test.ejb.wildflyconsulregistrar.api.ConsulRegistrar;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
#Startup
#Singleton
public class WildflyConsulRegistrarStartupBean {
#Inject
private ConsulRegistrar consulRegistrar;
#PostConstruct
public void initialize() {
registerServices();
}
private void registerServices() {
consulRegistrar.registerService("WildflyTestCluster");
}
.............
}
ConsulRegistrar code:
package ru.wildfly.test.ejb.wildflyconsulregistrar.impl;
import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.agent.model.NewService;
import ru.test.ejb.wildflyconsulregistrar.api.ConsulRegistrar;
import ru.wildfly.test.ejb.wildflyconsulregistrar.serversettings.api.CurrentServerNodeSettings;
import javax.annotation.PostConstruct;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
#Dependent
public class ConsulRegistrarImpl implements ConsulRegistrar {
...............
#Inject
private CurrentServerNodeSettings currentServerNodeSettings;
.............
#Override
public void registerService(String serviceName) {
String currentNodeName = currentServerNodeSettings.getCurrentNodeName();
........................
}
.......................
}
CurrentServerNodeSettings code:
package ru.wildfly.test.ejb.wildflyconsulregistrar.serversettings.impl;
import ru.wildfly.test.ejb.wildflyconsulregistrar.serversettings.api.CurrentServerNodeSettings;
import javax.enterprise.context.Dependent;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
#Dependent
public class CurrentServerNodeSettingsWildflyImpl implements CurrentServerNodeSettings {
....................
#Override
public String getCurrentNodeName() {
String currentNodeName = getPlatformMBeanServerAttributeValue(String.class, "jboss.as:system-property=server.name", "value");
return currentNodeName;
}
private <T> T getPlatformMBeanServerAttributeValue(Class<T> valueType, String objectName, String attributeName) {
T attributeValue = null;
try {
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
Object attributeObject = mBeanServer.getAttribute(new ObjectName(objectName), attributeName);
attributeValue = attributeObject != null ? (valueType.cast(attributeObject)) : null;
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
return attributeValue;
}
}
Error message:
Caused by: java.lang.IllegalStateException:
javax.management.AttributeNotFoundException:
"WFLYCTL0216: Management resource '[(\"system-property\" => \"server.name\")]' not found"
at ru.wildfly.test.ejb.wildflyconsulregistrar.serversettings.impl.CurrentServerNodeSettingsWildflyImpl
.getPlatformMBeanServerAttributeValue(CurrentServerNodeSettingsWildflyImpl.java:41)
I have found the same issue on jboss forum https://developer.jboss.org/message/971717#971717 , but it was unanswered.
Any suggestions?
This is a dependency problem during startup, i.e. the server name is set after your #PostConstruct method gets executed. Try to load the server name lazy when it is accessed from the application for the first time.
In Wildfly there is no generic way to enforce the sequence of deployments from the application despite the definition of module dependencies. But this won't help in your case.

Categories

Resources