I am consuming a Soap WebService using spring WebServiceTemplate & below is the bean creation and my bean class but dont know why i am unable to get the value of Default Uri.
Can someone please help with this thing.
ServiceContext.java
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.canaldigital.tsi.schema.psd.psd_managecustomer.v2");
return marshaller;
}
#Bean
public SaajSoapMessageFactory messageFactory() {
SaajSoapMessageFactory factory=new SaajSoapMessageFactory();
factory.setSoapVersion(SoapVersion.SOAP_12);
return factory;
}
#Bean
public ManageService voucherService(Jaxb2Marshaller marshaller,SaajSoapMessageFactory messageFactory) {
ManageService service = new ManageService();
service.setDefaultUri("http://localhost:7001/CustomerService?WSDL");
service.setMarshaller(marshaller);
service.setUnmarshaller(marshaller);
service.setMessageFactory(messageFactory);
return service;
}
ManageService.java
public class ManageService extends WebServiceGatewaySupport {
try{
System.out.println("Finalyy calllingggg service: "+getWebServiceTemplate());
System.out.println("WebService template URI is: ---- "+getWebServiceTemplate().getDefaultUri());
JAXBElement<GetCustomerInfoRequestType> mustangRequst=new createGetCustomerInfoRequest(customer);
(JAXBElement<GetCustomerInfoResponseType>) getWebServiceTemplate().marshalSendAndReceive(mustangRequst);
}catch(Exception e){
e.printStackTrace();
}
}
you should use #Autowired when you call your client that extends WebServiceGatewaySupport
Check that you don't have #Service annotation on the service.
Related
I have a java spring configuration defined like so,
#Configuration
public class FirstConfiguration {
#Bean
FirstController firstController() {
return new FirstController(firstService());
}
#Bean
FirstService firstService() {
return new FirstServiceImpl(secondService());
}
}
Now the beans in this configuration depend on SecondConfiguration defined like so,
#Configuration
public class SecondConfiguration {
#Bean
SecondController SecondController() {
return new SecondController(SecondService());
}
#Bean
SecondService secondService() {
return new SecondServiceImpl();
}
}
How can I make use of the secondService() bean in my FirstConfiguration?
Since the SecondService is a bean, you could inject it into the firstService method to configure another bean:
#Bean
FirstService firstService(#Autowired SecondService secondService) {
return new FirstServiceImpl(secondService);
}
You can inject the firstService like this :
#Autowired
SecondService secondService
You can refer the method secondService() directly when you import the configuration.
#Configuration
#Import(SecondConfiguration.class)
public class FirstConfiguration {
#Bean
FirstController firstController() {
return new FirstController(firstService());
}
#Bean
SomeController someController() {
return new SomeController(secondService());
}
}
Refer the Spring config import
I have checked many SO comments and the docs for spring data and unit testing but I cant get this to work and I dont know why its not working.
I have a junit test class that looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class DealServiceTest {
#Configuration
static class ContextConfiguration {
// this bean will be injected into the OrderServiceTest class
#Bean
public DealService orderService() {
DealService dealService = new DealService();
// set properties, etc.
return dealService;
}
#Bean
public EmployeeService employeeService(){
EmployeeService employeeService = new EmployeeService();
return employeeService;
}
}
#Autowired
DealService dealService;
#Autowired
EmployeeService employeeService;
#Test
public void createDeal() throws ServiceException {
Employee employee = new Employee("Daniel", "tuttle", "danielptm#me.com", "dannyboy", "secret password", 23.234, 23.23);
Deal d = dealService.createDeal("ADSF/ADSF/cat.jpg", "A title goes here", "A deal description", 23.22, "Name of business", 23.23,23.23, employee, "USA" );
Assert.assertNotNull(d);
}
}
And then I have my service class that looks like this
#Service
public class DealService {
#Autowired
private DealRepository dealRepository;
public Deal createDeal(String image, String title, String description, double distance, String location, double targetLat, double targetLong, Employee employee, String country) throws ServiceException {
Deal deal = new Deal(image, title, description, distance, location, targetLat, targetLong, employee, country);
try {
return dealRepository.save(deal);
}catch(Exception e){
throw new ServiceException("Could not create a deal: "+deal.toString(), e);
}
}
public Deal updateDeal(Deal d) throws ServiceException {
try{
return dealRepository.save(d);
}catch(Exception e){
throw new ServiceException("Could not update deal at this time: "+d.toString(),e);
}
}
public List<Deal> getAllDealsForEmployeeId(Employee employee) throws ServiceException {
try{
return dealRepository.getAllDealsBy_employeeId(employee.getId());
}catch(Exception e){
throw new ServiceException("Could not get deals for employee: "+employee.getId(), e);
}
}
}
And then my repository:
*/
public interface DealRepository extends CrudRepository<Deal, Long>{
public List<Deal> getDealsBy_country(String country);
public List<Deal> getAllDealsBy_employeeId(Long id);
}
My config file looks like this:
#Configuration
#EnableJpaRepositories("com.globati.repository")
#EnableTransactionManagement
public class InfrastructureConfig {
#Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName("com.mysql.jdbc.Driver");
config.setJdbcUrl("jdbc:mysql://localhost:3306/DatabaseProject");
config.setUsername("awesome");
config.setPassword("database");
return new HikariDataSource(config);
}
// #Bean
// public DataSource derbyDataSource(){
// HikariConfig config = new HikariConfig();
// config.setDriverClassName("jdbc:derby:memory:dataSource");
// config.setJdbcUrl("jdbc:derby://localhost:1527/myDB;create=true");
// config.setUsername("awesome");
// config.setPassword("database");
//
// return new HikariDataSource(config);
//
// }
#Bean
public JpaTransactionManager transactionManager(EntityManagerFactory factory) {
return new JpaTransactionManager(factory);
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setGenerateDdl(true);
return adapter;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource()); //Get data source config here!
factory.setJpaVendorAdapter(jpaVendorAdapter());
factory.setPackagesToScan("com.globati.model");
return factory;
}
}
But I get this error.
java.lang.IllegalStateException: Failed to load ApplicationContext ...
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean found for dependency
[com.globati.repository.DealRepository]: expected at least 1 bean
which qualifies as autowire candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Any suggestions for how I can successfully do unit testing with spring data, junit and with my service and repositories would be greatly appreciated. Thanks!
For a repository bean to be injected,
You need to enable Repositories, using one of the spring-data annotations. So add #Enable*Repositories to your configuration class
You also need dB factories and other related beans configured. I am using Mongo and I have mongoDbFactory bean configured
And for the most part your test configuration should look like your main configuration except for unnecessary bean replaced by mock implementations
UPDATE
Here is my code (sorry mine is in mongo, I think you can relate)
#Configuration
#WebAppConfiguration
#ComponentScan(basePackages = "com.amanu.csa",
excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = WebConfig.class))
#EnableMongoRepositories(repositoryImplementationPostfix = "CustomImpl")
class TestConfig {
#Bean
Mongo mongo() throws Exception {
return new MongoClient("localhost")
}
#Bean
MongoDbFactory mongoDbFactory() throws Exception {
return new SimpleMongoDbFactory(mongo(), "csa_test")
}
#Bean
MongoTemplate mongoTemplate() throws Exception {
MongoTemplate template = new MongoTemplate(mongoDbFactory())
template.setWriteResultChecking(WriteResultChecking.EXCEPTION)
return template
}
}
That is my test config file... As you can see it explicitly excludes my main configuration file.
#ContextConfiguration(classes = TestConfig)
#RunWith(SpringRunner.class)
class OrganizationServiceTest {
#Autowired
OrganizationService organizationService
#Test
void testRegister() {
def org = new Organization()
//...
organizationService.register(org)
// ...
}
And that is my test class. It refers to the test config, and I recommend using named config classes. You can put common options onto a super class and extend those and use them for your tests.
I hope this helps
You can try to add
#ActiveProfiles("your spring profile")
In addition I would suggest to use an embedded test db like flapdoodle (https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo)
You could either :
Mock your repository methods (Using Mockito for example)
Using an embedded database for your unit tests
I'm using Spring Boot 1.3.5 with Rest Controllers and everything is working fine.
I am also using Spring's validation sample techniques from the official documentation (JSR-303 Bean Validation API and Spring's validator interface, i tried both and faced the same problem) and the validations are working, but I am not able to configure custom messages.
I have configured a messages.properties file, and I can access the messages on this file just fine. However this validation seems not to be capable of reading or accessing my messages source (messages.properties) configured automatically via spring boot.
I can access the messages directly from the messages source object injected in controller via #Autowired (there's a comment in the code). However, the binding result of the Spring's validator interface or the JSR-303 Bean Validation seems to not be capable of accessing the messages.properties loaded in MessageSource. The result I have is that my errors have codes but don't have default messages.
Here is my Application class:
#SpringBootApplication
#ImportResource({ "classpath:security/cas-context.xml", "classpath:security/cas-integration.xml",
"classpath:security/security.xml" })
#EnableAutoConfiguration(exclude = VelocityAutoConfiguration.class) // http://stackoverflow.com/questions/32067759/spring-boot-starter-cache-velocity-is-missing
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public ServletRegistrationBean cxfServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/services/*");
}
#Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
#Bean
public Nfse nfseService() {
return new NfseImpl();
}
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), nfseService());
endpoint.publish("/nfseSOAP");
return endpoint;
}
}
Here is my Bean:
public class Protocolo {
private Long id;
#NotNull
#Min(1)
#Max(1)
private String protocolo;
private StatusProtocoloEnum status;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProtocolo() {
return protocolo;
}
public void setProtocolo(String protocolo) {
this.protocolo = protocolo;
}
public StatusProtocoloEnum getStatus() {
return status;
}
public void setStatus(StatusProtocoloEnum status) {
this.status = status;
}
}
Here is My rest controller:
#RestController
public class ProtocoloController {
#Autowired
private MessageSource messageSource;
#Autowired
private ProtocoloDAO protocoloDAO;
#RequestMapping(value = "/prot", method = RequestMethod.POST)
public void testar(#Valid #RequestBody Protocolo p) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
System.out.println(auth.getAuthorities());
System.out.println(messageSource.getMessage("protocolo.tamanho", null, null));
// IN THIS PART I'M ABLE TO PRINT THE MESSAGE IF VALIDATION IS DISABLED
System.out.println(p.getProtocolo());
}
}
So, this code works fine and the method is not called since i'm calling the method with a invalid Protocolo. However, my angularJS client receives the response with the errors codes populated but with all the default messages empty since the validation is not seeing my loaded messages.properties.
Is there a way to make my Spring validation Interfaces or JSR-303 validation incorporate the loaded message.properties (messagesource) in spring boot ? How can i correct this ? If it's necessary i can paste my code sample of Spring Validation interfaces also.
Thank's a lot,
Tarcísio.
TEST CODE:
#RestController
public class ProtocoloController {
#Autowired
private MessageSource messageSource;
#Autowired
private ProtocoloDAO protocoloDAO;
#RequestMapping(value = "/prot", method = RequestMethod.POST)
public void testar(#Valid #RequestBody Protocolo p, BindingResult bindingResult) {
System.out.println(messageSource.getMessage("Min.protocolo.protocolo", null, null));
if (bindingResult.hasErrors()) {
System.out.println(bindingResult.getFieldError().getDefaultMessage());
System.out.println(bindingResult.getFieldError().getCode());
}
System.out.println(p.getProtocolo());
}
}
Edit:
Known Bug in Spring Boot 1.5.3 see https://github.com/spring-projects/spring-boot/issues/8979
In Spring Boot since 1.5.3 you need to do this
#Configuration
public class ValidationMessageConfig {
#Bean
public LocalValidatorFactoryBean mvcValidator(MessageSource messageSource) {
LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
factory.setValidationMessageSource(messageSource);
return factory;
}
}
and then it will work.
With version 1.5.2 and before you can extend WebMVcConfigurerAdapter
#Configuration
public class ProfileMvcConfig extends WebMvcConfigurerAdapter {
private MessageSource messageSource;
#Autowired
public ProfileMvcConfig(MessageSource messageSource) {
this.messageSource = messageSource;
}
/**
* This method is overridden due to use the {#link MessageSource message source} in bean validation.
*
* #return A Validator using the {#link MessageSource message source} in bean validation.
*/
#Override
public Validator getValidator() {
LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
factory.setValidationMessageSource(messageSource);
return factory;
}
}
also see the documentation
In Spring Boot applicaton MessageSource is configured with a MessageSourceAutoConfiguration and you don't need to autowire it. For jsr303, create proper key-value pair in the messages.properties file. For "protocolo" field, you should have following values in property file.
NotNull.protocolo.protocolo=Field cannot be left blank
Min.protocolo.protocolo=Minimum value must be {1}
You can also check messages from property file like below in your code.
public void testar(#Valid #RequestBody Protocolo p,BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
System.out.println(bindingResult.getFieldError().getDefaultMessage());
}
}
you should have following values in property file:
Min.protocolo.protocolo=Minimum value must be {1}
then in the controller you obtain the message by calling function getMessage from messageSource object
Test code:
#RequestMapping(value = "/prot", method = RequestMethod.POST)
public void testar(#Valid #RequestBody Protocolo p, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
bindingResult.getFieldErrors().forEach(fieldError ->
System.out.println(messageSource.getMessage(fieldError, Locale.getDefault()))
);
}
System.out.println(p.getProtocolo());
}
I solved this in custom message in Spring validation read the last part of my answer.
Check this example as well.
I used a custom validator with custom annotation. I needed to change code in my custom validator.
public class PersonValidator implements ConstraintValidator {
#Override
public boolean isValid(final Person person, final ConstraintValidatorContext context) {
if (somethingIsInvalid()) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Something is invalid.").addConstraintViolation();
return false;
}
return true;
}
}
I have following spring annotation based configuration:
#Bean
public MarshallingMessageConverter marshallingMessageConverter() {
return new MarshallingMessageConverter();
}
#Bean
public Jaxb2Marshaller jaxb2Marshaller() {
return new Jaxb2Marshaller();
}
I need to inject jaxb2Marshaller to marshallingMessageConverter using setter based injection before marshallingMessageConverter is initialized by Spring. After lot of Googling still can not find this kind of scenario. Please help !!
UPDATE: I don't have have access to both classes as they are inside a jar file. When I Autowire them in a third class something like:
#Autorwired MarshallingMessageConverter converter; //I need something like #Autorwired(setMarshaller = jaxb2Marshaller) where setMarshaller is the setter inside `MarshallingMessageConverter`
#Autowired Jaxb2Marshaller marshaller;
Can you pass the marshaller to the converter constructor? If so, you can use the autowired to create the marshaller and then in the method annotated with #Bean you pass in the constructor:
#Autowired Jaxb2Marshaller marshaller;
#Bean
public MarshallingMessageConverter marshallingMessageConverter() {
return new MarshallingMessageConverter(marshaller);
}
#Bean
public MarshallingMessageConverter marshallingMessageConverter(Jaxb2Marshaller marshaller) {
MarshallingMessageConverter converter = new MarshallingMessageConverter();
converter.whatEverMethodCallIsNeeded(marshaller);
return converter;
}
I got a working spring boot rest service. When the path is wrong it doesn't return anything. No response At all. At the same time it doesn't throw error either. Ideally I expected a 404 not found error.
I got a GlobalErrorHandler
#ControllerAdvice
public class GlobalErrorHandler extends ResponseEntityExceptionHandler {
}
There is this method in ResponseEntityExceptionHandler
protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
I have marked error.whitelabel.enabled=false in my properties
What else must I do for this service to throw a 404 not found response back to clients
I referred a lot of threads and don't see this trouble faced by anybody.
This is my main application class
#EnableAutoConfiguration // Sprint Boot Auto Configuration
#ComponentScan(basePackages = "com.xxxx")
#EnableJpaRepositories("com.xxxxxxxx") // To segregate MongoDB
// and JPA repositories.
// Otherwise not needed.
#EnableSwagger // auto generation of API docs
#SpringBootApplication
#EnableAspectJAutoProxy
#EnableConfigurationProperties
public class Application extends SpringBootServletInitializer {
private static Class<Application> appClass = Application.class;
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(appClass).properties(getProperties());
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public FilterRegistrationBean correlationHeaderFilter() {
FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
filterRegBean.setFilter(new CorrelationHeaderFilter());
filterRegBean.setUrlPatterns(Arrays.asList("/*"));
return filterRegBean;
}
#ConfigurationProperties(prefix = "spring.datasource")
#Bean
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
static Properties getProperties() {
Properties props = new Properties();
props.put("spring.config.location", "classpath:/");
return props;
}
#Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
WebMvcConfigurerAdapter webMvcConfigurerAdapter = new WebMvcConfigurerAdapter() {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).favorParameter(true).parameterName("media-type")
.ignoreAcceptHeader(false).useJaf(false).defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", MediaType.APPLICATION_JSON);
}
};
return webMvcConfigurerAdapter;
}
#Bean
public RequestMappingHandlerMapping defaultAnnotationHandlerMapping() {
RequestMappingHandlerMapping bean = new RequestMappingHandlerMapping();
bean.setUseSuffixPatternMatch(false);
return bean;
}
}
The solution is pretty easy:
First you need to implement the controller that will handle all error cases. This controller must have #ControllerAdvice -- required to define #ExceptionHandler that apply to all #RequestMappings.
#ControllerAdvice
public class ExceptionHandlerController {
#ExceptionHandler(NoHandlerFoundException.class)
#ResponseStatus(value= HttpStatus.NOT_FOUND)
#ResponseBody
public ErrorResponse requestHandlingNoHandlerFound() {
return new ErrorResponse("custom_404", "message for 404 error code");
}
}
Provide exception you want to override response in #ExceptionHandler. NoHandlerFoundException is an exception that will be generated when Spring will not be able to delegate request (404 case). You also can specify Throwable to override any exceptions.
Second you need to tell Spring to throw exception in case of 404 (could not resolve handler):
#SpringBootApplication
#EnableWebMvc
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
DispatcherServlet dispatcherServlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
}
}
Result when I use non defined URL
{
"errorCode": "custom_404",
"errorMessage": "message for 404 error code"
}
UPDATE: In case you configure your SpringBoot application using application.properties then you need to add the following properties instead of configuring DispatcherServlet in main method (thanks to #mengchengfeng):
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false
I know this is an old question but here is another way to configure the DispatcherServlet in code but not in the main class. You can use a separate #Configuration class:
#EnableWebMvc
#Configuration
public class ExceptionHandlingConfig {
#Autowired
private DispatcherServlet dispatcherServlet;
#PostConstruct
private void configureDispatcherServlet() {
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
}
}
Please not that this does not work without the #EnableWebMvc annotation.
Add this to your Properties file.
spring:
mvc:
throw-exception-if-no-handler-found: true
web:
resources:
add-mappings: false
In your #ControllerAdvice class add this:
#ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<Object> handleNoHandlerFound404() {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);;
}