Spring Boot CXF service throws an exception with JPA - spring

In my Spring Boot app there are a jpa/hibernate class for persistance and a service for business logic using jpa directly. When I test the app whith JUnit, service works properly but when I use it inside a Soap WS it throws an unknown exception.
The WS code is the next:
package sample.ws.service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebParam.Mode;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
import sample.ws.model.Student;
#WebService(targetNamespace = "http://service.ws.sample/", name = "StudentWS")
#SOAPBinding(style=Style.RPC, use=Use.LITERAL)
public interface StudentWS {
#WebResult(name = "return", targetNamespace = "")
#RequestWrapper(localName = "getStudentByIdRequest",
targetNamespace = "http://service.ws.sample/",
className = "java.lang.Long")
#WebMethod(action = "urn:GetStudentById")
#ResponseWrapper(localName = "getStudentByIdResponse",
targetNamespace = "http://service.ws.sample/",
className = "sample.ws.model.Student")
public Student getStudentById(#WebParam(name = "id", targetNamespace = "", mode= Mode.IN) Long id);
}
package sample.ws.service;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sample.ws.bussines.StudentService;
import sample.ws.model.Student;
#javax.jws.WebService(serviceName = "StudentWebService", portName = "StudentPort", targetNamespace = "http://service.ws.sample/",
endpointInterface = "sample.ws.service.StudentWS")
public class StudentWSImpl implements StudentWS {
private static Logger logger = LoggerFactory.getLogger(StudentWSImpl.class);
#Autowired
private StudentService studentService;
public Student getStudentById(Long id) {
Student st = studentService.getStudentById(id);
logger.info(student.toString());
return student;
}
}
SoapUI reported error:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Fault occurred while processing.</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
And log contents:
2018-09-06 15:45:09.816[0;39m [33m WARN[0;39m [35m28024[0;39m [2m---[0;39m [2m[nio-8080-exec-8][0;39m [36mo.a.cxf.phase.PhaseInterceptorChain [0;39m [2m:[0;39m Application {http://service.ws.sample/}StudentWebService#{http://service.ws.sample}getStudentById has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: null
at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:162) ~[cxf-core-3.2.6.jar:3.2.6]
at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.createFault(AbstractJAXWSMethodInvoker.java:267) ~[cxf-rt-frontend-jaxws-3.2.6.jar:3.2.6]
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:128) ~[cxf-core-3.2.6.jar:3.2.6]

The problem was fixed by using #Autowired annotation. I changed it by #Resource and all is working properly. Now I am trying to know what is the difference between both annotations in that context.
More specifically, in StudentWSImpl implementation class, there was a call to
#Autowired
private StudentService studentService;
but now appears something like that:
#Resource
private StudentService studentService;

Related

How to print traceId and spanId with brave tracing?

Earlier i used to write below code with spring boot 1.5.12 :-
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
#Autowired
Tracer tracer;
Span span = this.tracer.getCurrentSpan();
System.out.println(Span.idToHex(span.getSpanId()));
System.out.println(Span.idToHex(span.getTraceId()));
But this code is not working with spring boot 2.2.6 .How should i print now ?
import brave.Tracer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Slf4j
#Component
public class BravePrinter {
#Autowired
private Tracer tracer;
public void print() {
var span = this.tracer.currentSpan();
System.out.println(span.context().traceIdString());
System.out.println(span.context().spanIdString());
}
}

Feign Client couldn't find custom registered eureka service

I will tell little bit about what I am trying to achieve. I have a spring boot application which is an Eureka client and registers itself as a data-service service. After this application startup (ApplicationReadeEvent.class) I am registering also another custom created Eureka client and seems the registration is successful. I am able to see that newly registered service (workflow-service) when accessing to http://localhost:8761. The reason I decided to do it inside data-service application is because I needn't it out of this context and I need it only in DEV environment. Later instead of it would be plugged the real workflow-service developed by other team.
The problem here is that when I trying to access to this service through a feign client I am receiving an exception:
com.netflix.client.ClientException: Load balancer does not have available server for client: workflow-service
Here is my custom service registration code:
package XXX;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryClient;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.model.HttpRequest;
import org.mockserver.model.HttpResponse;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtilsProperties;
import org.springframework.cloud.netflix.eureka.*;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import java.net.SocketException;
#Configuration
#ConditionalOnExpression("${workflow.engine.mock.enabled:false}")
public class MockWorkflowEngineConfiguration {
#Value("${workflow.engine.mock.application.name}") private String workflowEngineApplicationName;
#Value("${workflow.engine.mock.application.port}") private Integer workflowEnginePort;
#Autowired private EurekaInstanceConfigBean originalInstanceConfig;
#Autowired private EurekaClientConfigBean originalClientConfig;
#Autowired private ApplicationInfoManager applicationInfoManager;
#Autowired private ApplicationContext applicationContext;
#Autowired private ApplicationEventPublisher applicationEventPublisher;
#Autowired private ObjectProvider<HealthCheckHandler> healthCheckHandler;
#Autowired private EurekaServiceRegistry eurekaServiceRegistry;
private EurekaRegistration workflowEngineEurekaRegistration;
private DiscoveryClient workflowEngineDiscoveryClient;
private ClientAndServer workflowEngineMockClient;
#EventListener(ApplicationReadyEvent.class)
public void initializeMockWorkflowEngine() throws SocketException{
workflowEngineDiscoveryClient = new CloudEurekaClient(
createWorkflowEngineAppInfoManager(),
duplicateEurekaClientConfig(),
applicationEventPublisher);
workflowEngineEurekaRegistration = EurekaRegistration.builder((CloudEurekaInstanceConfig) workflowEngineDiscoveryClient.getApplicationInfoManager().getEurekaInstanceConfig())
.with(workflowEngineDiscoveryClient)
.with(workflowEngineDiscoveryClient.getApplicationInfoManager())
.with(healthCheckHandler).build();
eurekaServiceRegistry.register(workflowEngineEurekaRegistration);
workflowEngineMockClient = new ClientAndServer(workflowEnginePort);
workflowEngineMockClient.when(
HttpRequest.request()
.withMethod("GET")
.withPath("/job")
)
.respond(
HttpResponse.response()
.withStatusCode(200)
.withBody("{ id: '1', name: 'default'}")
);
}
#EventListener(ContextClosedEvent.class)
public void shutdownMockWorkflowEngine(){
workflowEngineDiscoveryClient.shutdown();
eurekaServiceRegistry.deregister(workflowEngineEurekaRegistration);
workflowEngineMockClient.stop(true);
}
private ApplicationInfoManager createWorkflowEngineAppInfoManager() throws SocketException {
EurekaInstanceConfigBean newInstanceConfig =
new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties()));
newInstanceConfig.setEnvironment(applicationContext.getEnvironment());
newInstanceConfig.setAppname(workflowEngineApplicationName);
newInstanceConfig.setInstanceId(applicationInfoManager.getInfo().getHostName() + ":" + workflowEngineApplicationName + ":" + workflowEnginePort);
newInstanceConfig.setInitialStatus(InstanceInfo.InstanceStatus.UP);
newInstanceConfig.setNonSecurePortEnabled(originalInstanceConfig.isNonSecurePortEnabled());
newInstanceConfig.setNonSecurePort(workflowEnginePort);
newInstanceConfig.setHostname(applicationInfoManager.getInfo().getHostName());
newInstanceConfig.setSecurePortEnabled(originalInstanceConfig.isSecurePortEnabled());
newInstanceConfig.setSecurePort(originalInstanceConfig.getSecurePort());
newInstanceConfig.setDataCenterInfo(originalInstanceConfig.getDataCenterInfo());
newInstanceConfig.setHealthCheckUrl(originalInstanceConfig.getHealthCheckUrl());
newInstanceConfig.setSecureHealthCheckUrl(originalInstanceConfig.getSecureHealthCheckUrl());
newInstanceConfig.setHomePageUrl(originalInstanceConfig.getHomePageUrl());
newInstanceConfig.setStatusPageUrl(originalInstanceConfig.getStatusPageUrl());
newInstanceConfig.setStatusPageUrlPath(originalInstanceConfig.getStatusPageUrlPath());
newInstanceConfig.setIpAddress(originalInstanceConfig.getIpAddress());
newInstanceConfig.setPreferIpAddress(originalInstanceConfig.isPreferIpAddress());
ApplicationInfoManager manager =
new ApplicationInfoManager(newInstanceConfig, (ApplicationInfoManager.OptionalArgs) null);
return manager;
}
private EurekaClientConfigBean duplicateEurekaClientConfig() {
EurekaClientConfigBean newConfig = new EurekaClientConfigBean();
newConfig.setFetchRegistry(false);
newConfig.setEurekaServerPort(originalClientConfig.getEurekaServerPort());
newConfig.setAllowRedirects(originalClientConfig.isAllowRedirects());
newConfig.setAvailabilityZones(originalClientConfig.getAvailabilityZones());
newConfig.setBackupRegistryImpl(originalClientConfig.getBackupRegistryImpl());
newConfig.setServiceUrl(originalClientConfig.getServiceUrl());
return newConfig;
}
}
And here is my feign client code:
#FeignClient(name = "workflow-service", configuration = FeignClientConfiguration.class)
public interface WorkflowService {
#RequestMapping(value = "/job", method = RequestMethod.GET, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<List<WorkflowJobDTO>> listJobs();
Here is the feign client usage through which I am trying to access to another service:
#GetMapping(path = "/workflow-jobs", produces = "application/json")
public ResponseEntity<List<WorkflowJobDTO>> getAllJobs() {
return workflowService.listJobs();
}
}
This has been fixed by just setting virtual host name.
newInstanceConfig.setVirtualHostname(workflowEngineApplicationName);

Spring find 2 candidates, but there is only one

I'm trying upgrade a JHipster project, however I found the following issue:
Description:
Parameter 0 of constructor in com.cervaki.config.AsyncConfiguration required a single bean, but 2 were found:
- jhipster-io.github.jhipster.config.JHipsterProperties: defined in null
- io.github.jhipster.config.JHipsterProperties: defined in null
Action:
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed
What I understood is that spring can't inject the correct bean because there are two candidates, but I only have the io.github.jhipster.config.JHipsterProperties implementation:
package com.cervaki.config;
import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
import io.github.jhipster.config.JHipsterProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.*;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
#Configuration
#EnableAsync
#EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {
private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
private final JHipsterProperties jHipsterProperties;
public AsyncConfiguration(JHipsterProperties jHipsterProperties) {
this.jHipsterProperties = jHipsterProperties;
}
#Override
#Bean(name = "taskExecutor")
public Executor getAsyncExecutor() {
log.debug("Creating Async Task Executor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
executor.setThreadNamePrefix("cervaki-Executor-");
return new ExceptionHandlingAsyncTaskExecutor(executor);
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}
You can download the pom.xml here.
I did a search in the entire code and libs to find the jhipster-io.github.jhipster.config.JHipsterProperties file, however I didn't find anything.
What can I do to solve this problem?
I also faced this issue after generating new JhipsterApp,
And as you - I don't find the "jhipster-io" dependencies in project
How I solve this:
in src/main/java/your/package/config create a "AppConfiguration.java"
with content:
import io.github.jhipster.config.JHipsterProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
#Configuration
public class AppConfiguration {
#Bean
#Primary
public JHipsterProperties jHipsterProperties() {
return new JHipsterProperties();
}
}
even without #Primary - I haven't got this error

Integration test with jersey and spring boot 1.4.0.RELEASE

I am trying to write integration test with jersey, Spring boot 1.4 and Spring data jpa.I am able to start embedded server but getting error from jersey side , any help will be appreciated.
Integration test
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT, classes=Application.class)
public class ContactServiceIT {
#Autowired
private TestRestTemplate restTemplate;
#Autowired
private ContactDao contactDao;
#Test
public void mergeContactsTest() {
String body = this.restTemplate.getForObject("/contacts/merge", String.class);
assertThat(body).isEqualTo("contacts merged");
}
}
Contact Resource
import java.io.IOException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.springframework.beans.factory.annotation.Autowired;
#Path("/contacts")
public class ContactResource {
#Autowired
private ContactService contactService;
#GET
#Path("merge")
public Response mergeContacts() throws IOException {
contactService.mergeContacts();
return Response.status(Response.Status.CREATED)
.entity("contacts merged").build();
}
}
Stack trace:
java.lang.NoSuchMethodError: org.glassfish.jersey.CommonProperties.getValue(Ljava/util/Map;Ljavax/ws/rs/RuntimeType;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
at org.glassfish.jersey.jackson.JacksonFeature.configure(JacksonFeature.java:73) ~[jersey-media-json-jackson-2.23.1.jar:na]
at org.glassfish.jersey.model.internal.CommonConfig.configureFeatures(CommonConfig.java:680) ~[jersey-common-2.7.jar:na]
at org.glassfish.jersey.model.internal.CommonConfig.configureMetaProviders(CommonConfig.java:610) ~[jersey-common-2.7.jar:na]
at org.glassfish.jersey.server.ResourceConfig.configureMetaProviders(ResourceConfig.java:800) ~[jersey-server-2.7.jar:na]
Please let me know if I am missing something.
Thanks.

Spring defaultrollback after class

I have an Integration test using TestNG for a DAO class manager by Spring/Hibernate. As shown below. I was trying to have one test insert the data and then other test just to test the fetch method. So I have used dependsOn provided by TestNG. But now the problem is once my first test ends it roll backs the transaction as I have given defaultRollBack = true in TransactionConfiguration annotation. so my second test fails. Is there any way to stop it and rollback after all the tests in class are done?
import static org.testng.Assert.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.testng.annotations.Test;
import com.worksheet.State;
#ContextConfiguration("classpath*:spring-context-test.xml")
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
#Transactional(propagation = Propagation.REQUIRES_NEW)
public class StateDAOTest extends AbstractTransactionalTestNGSpringContextTests{
#Autowired
private StateDAO stateDAO;
#Test
public void saveUnknownState(){
State state = new State("Unknown", "UKN");
stateDAO.saveState(state);
assertTrue(state.getId() > 0);
}
#Test(dependsOnMethods = {"saveUnknownState"})
public void fetchUnknownState(){
State state = stateDAO.getStateByAbbreviation("UKN");
assertNotNull(state);
}
}

Resources