I am running a Spring batch but for logging purposes, I am redirecting all my logs to Splunk. The logs are getting updated on Splunk as expected, but now my job is not terminating. Even after everything gets processed, it's still running.
How can I terminate my job with Splunk logging enabled?
log4j2.xml :
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" name="cspprovmi"
packages="com.prov">
<Appenders>
<SplunkHttp name="http" url="${env:SPLUNK_URL}"
token="${env:SPLUNK_TOKEN}" host="${env:SPLUNK_NAMESPACE}"
index="cba_facts_cs" source="${env:SPLUNK_SOURCE}"
sourcetype="facts_cs:http:log" messageFormat="json"
disableCertificateValidation="true">
<PatternLayout pattern="%msg" />
</SplunkHttp>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="info" additivity="false">
<AppenderRef ref="http" level="info" />
</Root>
</Loggers>
</Configuration>
pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
JobBuilderConfig.java
// Job
#Bean
public Job job(){
return jobBuilderFactory.get("jobCSProvMI4275")
.start(step1())
.next(step2())
.next(step3())
.next(step4())
.next(step5())
.next(step6())
.next(step7())
.incrementer(new RunIdIncrementer())
.build();
}
}
One workaround I am considering is to include jobListener and call system.exit(0) in the code itself. This seems to work fine, as it's terminating job even with Splunk logging enabled, but not sure if there is a better way to achieve this (ie exit the process gracefully).
#Bean
public JobExecutionListener jobMi4275ExecutionListener() {
JobExecutionListener jobExecutionListener = new JobExecutionListener() {
#Override
public void beforeJob(JobExecution jobExecution) {
LOGGER.info("jobCSP4275 Started executing..");
}
#Override
public void afterJob(JobExecution jobExecution) {
LOGGER.info("jobCSP4275 finished successfully..Exiting job !!");
System.exit(0);
}
};
return jobExecutionListener;
}
Related
I am trying to run this test on Arquillian:
#ExtendWith(ArquillianExtension.class)
class ArquillianTest {
#Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class, "arquillian-test.war");
}
#Test
void execTest() {
fail("Always fails");
}
}
but it gets ignored and the whole execution just fails with:
INFO: JBoss Threads version 3.1.0.Final
Test ignored.
java.lang.NoClassDefFoundError: org/jboss/threads/AsyncFuture
at org.jboss.as.controller.client.ModelControllerClient$Factory.create(ModelControllerClient.java:609)
at org.jboss.as.arquillian.container.CommonDeployableContainer.start(CommonDeployableContainer.java:121)
at org.jboss.arquillian.container.impl.ContainerImpl.start(ContainerImpl.java:179)
I do not think I am missing anything in my deployment method, since there are no classes involved in this simple test, but I am new to Arquillian.
I found a bug report of the same error, but it was in 2014 and apparently resolved: https://lists.jboss.org/pipermail/jboss-jira/2014-April/256446.html
This is my pom.xml (relevant parts):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</plugin>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.7.0.Alpha10</version>
<type>pom</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit5</groupId>
<artifactId>arquillian-junit5-container</artifactId>
<version>1.7.0.Alpha10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.protocol</groupId>
<artifactId>arquillian-protocol-servlet-jakarta</artifactId>
<version>1.7.0.Alpha10</version>
</dependency>
<dependency>
<groupId>org.wildfly.arquillian</groupId>
<artifactId>wildfly-arquillian-container-managed</artifactId>
<version>5.0.0.Alpha2</version>
<scope>test</scope>
</dependency>
and this is my arquillian.xml:
<arquillian
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<defaultProtocol type="Servlet 5.0"/>
<container qualifier="wildfly" default="true">
<configuration>
<property name="jbossHome">C:\Users\sotan\Software\wildfly-preview-25.0.1.Final</property>
<property name="javaVmArguments">-Djboss.socket.binding.port-offset=100</property>
<property name="managementPort">10090</property>
</configuration>
</container>
</arquillian>
I'm creating a REST Service with Apache Camel and CXF-RS, using the following tutorial: https://www.javainuse.com/camel/apache_camel_rest_cxfrs
I've set up the code as shown in the tutorial and followed the steps correctly. After building the Maven project, I have successfully been able to install the bundle on Apache Karaf, using the SNAPSHOT file created. (A new Bundle ID was created).
When I run the command to 'start' the newly created bundle, it seemingly works with no errors being shown. However, when I access http://localhost:8181/cxf as mentioned towards the end of the tutorial, it says 'No services have been found':
Can you please advise me on what could be causing this problem?
Thank you.
My Project Structure:
My Code:
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fuseproject</groupId>
<artifactId>camel-cxfrs-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>bundle</packaging>
<repositories>
<repository>
<id>Central2</id>
<name>Central2</name>
<url>https://repo.maven.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
<version>2.12.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<version>2.4.0</version>
</plugin>
</plugins>
</build>
</project>
CamelProcessor.java:
package com.fuseproject.beans;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
public class CamelProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
// Get input from exchange
String msg = exchange.getIn().getBody(String.class);
// set output in exchange
exchange.getOut().setBody("Hello World " + msg);
}
}
EmployeeServiceResource.java:
package com.fuseproject.beans;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
#Path("/")
public class EmployeeServiceResource {
public EmployeeServiceResource() {
}
#GET
#Path("/employees/{name}/")
public String getCustomer(#PathParam("name") String name) {
return null;
}
}
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/cxf"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<cxf:rsServer id="restService" address="http://localhost:9000/employeeservice"
serviceClass="com.fuseproject.beans.EmployeeServiceResource">
</cxf:rsServer>
<bean id="processor" class="com.fuseproject.beans.CamelProcessor" />
<camelContext id="camelId" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="cxfrs://bean://restService" />
<process ref="processor" />
</route>
</camelContext>
</beans>
I am getting a 404 error when I test my REST Spring WebService in Postman.
Can anyone suggest a solution??
My code :
src/main/resources/spring/application-config.xml
-------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Uncomment and add your base-package here:
<context:component-scan
base-package="org.springframework.samples.service"/> -->
</beans>
-------------------------------------------------------------------------------------------------------------------------------------------
src/main/resources/logback.xml
-------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration file for LogBack (slf4J implementation)
See here for more details: http://gordondickens.com/wordpress/2013/03/27/sawing-through-the-java-loggers/ -->
<configuration scan="true" scanPeriod="30 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<!-- To enable JMX Management -->
<jmxConfigurator/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5level %logger{0} - %msg%n</pattern>
</encoder>
</appender>
<!--<logger name="org.hibernate" level="debug"/> -->
<!-- Uncomment and add your logger here:
<logger name="org.springframework.samples.service.service" level="debug"/> -->
<root level="info">
<appender-ref ref="console"/>
</root>
</configuration>
---------------------------------------------------------------------------------------------------------------------------------------------
src/main/webapp/WEB-INF/mvc-config.xml
---------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Uncomment and your base-package here:
<context:component-scan
base-package="org.springframework.samples.web"/> -->
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
---------------------------------------------------------------------------------------------------------------------------------------------
src/main/webapp/WEB-INF/web.xml
---------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>ManageUserRoles</display-name>
<!--
- Location of the XML file that defines the root application context.
- Applied by ContextLoaderListener.
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
- Servlet that dispatches request to registered handlers (Controller implementations).
-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
//////////////////////////Controller///////////////////////////////
package com.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.model.Role;
#Controller
public class RoleController {
private static final Logger logger = LoggerFactory.getLogger(RoleController.class);
Map<String, Role> roleData = new HashMap<String, Role>();
#RequestMapping(value = "/role/{role_name}", method = RequestMethod.GET,headers="Accept=application/json")
public #ResponseBody Role findRole(#PathVariable("role_name") String role_name)
{
logger.info("Get a single role with name="+role_name);
return roleData.get(role_name);
}
#RequestMapping(value = "/roles", method = RequestMethod.GET)
public #ResponseBody List<Role> getAllRoles()
{
logger.info("Start getAllRoles.");
List<Role> list_roles = new ArrayList<Role>();
list_roles = createRoleList();
return list_roles;
}
public List<Role> createRoleList()
{
Role role1 = new Role("NP Sherm Test", "NP Test", "Active");
Role role2 = new Role("Sherm Employee Test", "Employee access test role", "Active");
Role role3 = new Role("Sherm Manager Test", "Manager test user role", "Active");
List<Role> list_roles = new ArrayList<Role>();
list_roles.add(role1);
list_roles.add(role2);
list_roles.add(role3);
return list_roles;
}
#RequestMapping(value="/roles/new/",method=RequestMethod.POST,headers="Accept=application/json")
public #ResponseBody Role addRole(#RequestBody Role role)
{
logger.info("Start Add Role");
Role roleGet = roleData.put(role.getRole_name(), role);
return roleGet;
}
#RequestMapping(value="/roles/new/",method=RequestMethod.PUT,headers="Accept=application/json")
public #ResponseBody Role editRole(#RequestBody Role role)
{
Role role_update = new Role();
role.setRole_name(role.getRole_name());
role.setRole_desc(role.getRole_desc());
role.setRole_status(role.getRole_status());
return role_update;
}
}
/////////////////////////////////////Model///////////////////////////////
package com.model;
public class Role {
private String role_name;
private String role_desc;
private String role_status;
public Role(){}
public Role(String role_name, String role_desc, String role_status) {
super();
this.role_name = role_name;
this.role_desc = role_desc;
this.role_status = role_status;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
public String getRole_desc() {
return role_desc;
}
public void setRole_desc(String role_desc) {
this.role_desc = role_desc;
}
public String getRole_status() {
return role_status;
}
public void setRole_status(String role_status) {
this.role_status = role_status;
}
}
//////////////////////////////pom.xml//////////////////////////////////
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples.service.service</groupId>
<artifactId>ManageUserRoles</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Web -->
<jsp.version>2.2</jsp.version>
<jstl.version>1.2</jstl.version>
<servlet.version>2.5</servlet.version>
<!-- Spring -->
<spring-framework.version>3.2.3.RELEASE</spring-framework.version>
<!-- Hibernate / JPA -->
<hibernate.version>4.2.1.Final</hibernate.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
<!-- Test -->
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Other Web dependencies -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp.version}</version>
<scope>provided</scope>
</dependency>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Test Artifacts -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-framework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
As you don't have any specific application context, the problem is with the current URL mapping i.e., the URI ManageUserRoles did not map to the controller, so change the code as below:
#Controller("ManageUserRoles")
public class RoleController {
// Add all you existing handler methods
}
After your UPDATE 1:
Also, your componentscan is not correct in mvc-config.xml because of which controller can't be detected:
base-package="org.springframework.samples.web" change it to base-package="com.controller"
I am using Spring MVC 4.1.5 with its REST support trying to get a web service working with google protocol buffers message format. I have seen a lot of posts that are mentioning this issue with JSON format but none with google protocol buffers format.
Also I don't see Spring framework docs have a MediaType for protobufs (more on that below) My code is posted here on github
Here's my controller code (using or not using produces="application-xprotobuf" makes no difference - same 406 not acceptable error)
#RestController
#RequestMapping("/ws")
#EnableWebMvc
public class CustomerRestController {
#Autowired
private CustomerRepository customerRepository;
//#RequestMapping(value="/customers/{id}", method = RequestMethod.GET, produces="application/x-protobuf")
#RequestMapping(value="/customers/{id}", method = RequestMethod.GET)
public CustomerProtos.Customer customer(#PathVariable Integer id) {
return this.customerRepository.findById(id);
}
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
private CustomerProtos.Customer customer(int id, String f, String l, Collection<String> emails) {
String emailAddressString = "defaultEmail#address.com";
for (String email : emails) {
emailAddressString = email;
break;
}
EmailAddress emailAddress = CustomerProtos.Customer.EmailAddress.newBuilder()
.setType(CustomerProtos.Customer.EmailType.PROFESSIONAL).setEmail(emailAddressString).build();
return CustomerProtos.Customer.newBuilder().setFirstName(f).setLastName(l).setId(id).addEmail(emailAddress)
// .addAllEmail(emailAddresses)
.build();
}
#Bean
CustomerRepository customerRepository() {
return new CustomerRepositoryImpl();
}
}
here's my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>demo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/rest-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
Here's my pom.xml, please note that i do have google protobuf libaries added here and they do end up in WEB-INF/lib folder of the deployed .war file.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.DemoApplication</start-class>
<java.version>1.8</java.version>
<jackson.version>2.5.3</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.protobuf-java-format</groupId>
<artifactId>protobuf-java-format</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-legacy</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Here's my test client
package demo;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class DemoApplicationTests {
#Configuration
public static class RestClientConfiguration {
#Bean
RestTemplate restTemplate(ProtobufHttpMessageConverter hmc) {
return new RestTemplate(Arrays.asList(hmc));
}
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
}
#Autowired
private RestTemplate restTemplate;
#Test
public void contextLoaded() {
ResponseEntity<CustomerProtos.Customer> customer = restTemplate.getForEntity(
"http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2", CustomerProtos.Customer.class);
System.out.println("customer retrieved: " + customer.toString());
}
}
When I run the client from command line using mvn test
I get the following error
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.697 sec <<< FAILURE! - in demo.DemoApplicationTests
contextLoaded(demo.DemoApplicationTests) Time elapsed: 0.037 sec <<< ERROR!
org.springframework.web.client.HttpClientErrorException: 406 Not Acceptable
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:641)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:597)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557)
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:289)
at demo.DemoApplicationTests.contextLoaded(DemoApplicationTests.java:42)
I saw people suggesting using a contentNegotiationManager
In my rest-servlet.xml I have mvc:annotation-driven tag
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="demo" />
<mvc:annotation-driven />
</beans>
Also I have dropped in a webConfig.java in demo package
package demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
/**
* Total customization - see below for explanation.
*/
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).
favorParameter(true).
parameterName("mediaType").
ignoreAcceptHeader(true).
useJaf(false).
defaultContentType(MediaType.TEXT_PLAIN).
mediaType("xml", MediaType.APPLICATION_XML).
mediaType("json", MediaType.APPLICATION_JSON).
mediaType("x-protobuf", MediaType.ALL)
;
}
}
I get the 406 not acceptable error with and without the webconfig.java (which is doing the work of contentNegotationManager).
I haven't been able to find a MediaType.APPLICATION_XPROTOBUF in Spring 4.1.3 or even 4.2.3 jars .
So I have left that value to MediaType.ALL ( I think that should work ?)
When I run the test client I get this message before actually running the test..
09:27:26.198 [main] DEBUG o.s.web.client.RestTemplate - Created GET request for "http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2"
09:27:26.199 [main] DEBUG o.s.web.client.RestTemplate - Setting request Accept header to [application/x-protobuf, text/plain, application/xml, application/json]
09:27:26.245 [main] DEBUG o.s.web.client.RestTemplate - GET request for "http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2" resulted in 406 (Not Acceptable); invoking error
handler
It clearly shows its setting the accept headers to include "application-xprotobuf" value as well.
Not sure what I am missing in this case.
I had the same issue with the controller failing with 406: Not Acceptable. After a lot of tracing I figured out the statement in the example:
Spring Boot automatically registers HttpMessageConverter beans so we need only define the ProtobufHttpMessageConverter bean and it gets configured appropriately.
is to be understood literally, since without Spring Boot no converter registration happens. The bean is instantiated, but it's never registered in the list of HttpMessageConverters.
I've solved it by explicitly registering a ProtobufHttpMessageConverter instance:
#Configuration
#EnableWebMvc
#ComponentScan
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new ProtobufHttpMessageConverter());
super.configureMessageConverters(converters);
}
}
You don't need to declare a separate bean for it (unless you plan to call it explicitly).
Also note that overriding configureMessageConverters() disables all standard converters; if you mean to extend the list of stock converters rather than replace it, override extendMessageConverters() instead.
I am converting a project done using spring jms into spring boot project. I dont know how to convert the context.xml in spring jms into the configuration class in spring boot. My context.xml is as follows
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>file:./config-env-receiver.properties</value>
</property>
</bean>
<bean id="stepConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName">
<value>${mq.hostname.step}</value>
</property>
<property name="port">
<value>${mq.port.step}</value>
</property>
<property name="channel">
<value>${mq.channel.step}</value>
</property>
<property name="queueManager">
<value>${mq.queuemanager.step}</value>
</property>
<property name="transportType">
<value>1</value>
</property>
</bean>
<bean id="jmsDestination" class="com.ibm.mq.jms.MQQueue">
<constructor-arg value="${mq.queuename.step}" />
</bean>
<bean
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="stepConnectionFactory" />
<property name="sessionTransacted" value="true" />
<property name="destinationName" value="${mq.queuename.step}" />
<property name="exceptionListener" ref="exceptionListener" />
<property name="messageListener" ref="stepOutListenerItemCreateUpdate" />
</bean>
<bean id="exceptionListener" class="com.message.view.CustomException">
</bean>
<bean id="stepOutListenerItemCreateUpdate"
class="com.message.view.WMQueueMessageConsumer">
</bean>
<bean id="springConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="stepConnectionFactory" />
</bean>
<bean id="jmsTemplateStep" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="springConnectionFactory" />
<property name="defaultDestination" ref="jmsDestination" />
</bean>
<context:component-scan base-package="com.message.view">
</context:component-scan>
I tried creating the Application.class as follows.
package hello;
import java.util.Arrays;
import javax.jms.JMSException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.jms.connection.SingleConnectionFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import com.ibm.mq.jms.MQQueue;
import com.ibm.mq.jms.MQQueueConnectionFactory;
#SpringBootApplication
//#ImportResource("classpath:context_receiver.xml")
public class Application {
#Autowired
public CustomException customException;
#Autowired
public MessageListener messageListener;
#Bean
public MQQueueConnectionFactory getMQconnectionfactory(){
MQQueueConnectionFactory mqconfactory=new MQQueueConnectionFactory();
try {
mqconfactory.setHostName("*******");
mqconfactory.setPort(*****);
mqconfactory.setChannel("**********");
mqconfactory.setQueueManager("********");
mqconfactory.setTransportType(1);
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return mqconfactory;
}
#Bean
public MQQueue getMQQueue(){
return new MQQueue();
}
#Bean
public DefaultMessageListenerContainer getDefaultMessageListenerContainer(){
DefaultMessageListenerContainer defmesliscont=new DefaultMessageListenerContainer();
defmesliscont.setConnectionFactory(getMQconnectionfactory());
defmesliscont.setSessionTransacted(true);
defmesliscont.setDestinationName("********");
defmesliscont.setExceptionListener(customException);
defmesliscont.setMessageListener(messageListener);
return defmesliscont;
}
#Bean
public SingleConnectionFactory getSingleConnectionFactory(){
SingleConnectionFactory singleConnectionFactory=new SingleConnectionFactory();
singleConnectionFactory.setTargetConnectionFactory(getMQconnectionfactory());
return singleConnectionFactory;
}
#Bean
public JmsTemplate getJmsTemplate(){
JmsTemplate jmsTemplate=new JmsTemplate();
jmsTemplate.setConnectionFactory(getSingleConnectionFactory());
jmsTemplate.setDefaultDestination(getMQQueue());
return jmsTemplate;
}
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
}
But am getting this error.
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to load bean class: ; nested exception is java.lang.IllegalArgumentException: Attribute 'exclude' is of type [Class[]], but [String[]] was expected. Cause:
at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:383)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:162)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:296)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:240)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:609)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at hello.Application.main(Application.java:81)
Caused by: java.lang.IllegalArgumentException: Attribute 'exclude' is of type [Class[]], but [String[]] was expected. Cause:
at org.springframework.core.annotation.AnnotationAttributes.doGet(AnnotationAttributes.java:117)
at org.springframework.core.annotation.AnnotationAttributes.getStringArray(AnnotationAttributes.java:70)
at org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.selectImports(EnableAutoConfigurationImportSelector.java:69)
at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:379)
... 13 common frames omitted
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Failed to load bean class: ; nested exception is java.lang.IllegalArgumentException: Attribute 'exclude' is of type [Class[]], but [String[]] was expected. Cause:
at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:383)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:162)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:296)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:240)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:609)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at hello.Application.main(Application.java:81)
Caused by: java.lang.IllegalArgumentException: Attribute 'exclude' is of type [Class[]], but [String[]] was expected. Cause:
at org.springframework.core.annotation.AnnotationAttributes.doGet(AnnotationAttributes.java:117)
at org.springframework.core.annotation.AnnotationAttributes.getStringArray(AnnotationAttributes.java:70)
at org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.selectImports(EnableAutoConfigurationImportSelector.java:69)
at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:379)
... 13 more
I have even tried importing the context.xml using #ImportResource. But that too is not working. Though i prefer configuring it through the Application.class.
Please tell me what am doing wrong. Thanks.
I've got it working. Here is the snippet from thre working pom file
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
Upgrade you spring version to 4.1.5.RELEASE
I've got the same issue.
Looks like the problem is in incompatibility of EnableAutoConfiguration which is part of SpringBootApplication and https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAttributes.java. EnableAutoConfiguration has exclude as Class [], but AnnotationAttributes expects String []. Most likely the versions are incompatible. I did not come up with solution yet though.
close idea
regenerate idea configuration files
$ mvn idea:clean
$ mvn idea:idea
reimport projects
run again in the idea