#Resource returns null when getBean does not - java

I have a piece of code that uses Spring dependency injection with ApplicationContext
public abstract class BigDataParent {
private static final Logger log = LoggerFactory.getLogger(BigDataOperation.class);
protected static ApplicationContext context =
new ClassPathXmlApplicationContext("file.xml");
...
}
And the child:
public class BigBadChild extends BigDataParent {
private Something query;
#Override
public void doSomething() {
query = (Something) context.getBean("beanName");
....
}
}
I want to change the injection to use annotations instead of context, so I have just changed the child class to
public class BigBadChild extends BigDataParent {
#Resource(name = "beanName")
private Something query;
#Override
public void doSomething() {
// Removed query = (Something) context.getBean("beanName");
....
}
}
I have also changed my xml configuration file and have added
<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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
But now I'm getting that query is null. I bet that I am missing something basic, but what is it? Thank you.
EDIT:
Something is an interface that has several implementations, I'm choosing the implementation in the xml file file.xml. When I'm doing so using context.getBean(), it works and I have the right implementation, but when using #Reousrce (javax.annotation.Resource) I'm getting null.
What is the difference in flow when using context.getBean() and #Resource? Is there something different to how and when the values are initialized that might cause this?
EDIT #2: My list of dependencies:
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.2</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.3.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
<version>4.3.4.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.175</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
</dependencies>

By specifying
<context:annotation-config />
Spring registers a number of BeanPostProcessor beans to perform bean injection. One of these is CommonAnnotationBeanPostProcessor which handles #Resource annotated members.
This BeanPostProcessor is only registered if javax.annotation.Resource is on the classpath when the program runs.
You must be running the application without providing it to the classpath.
Note that you must be providing it at compilation time, otherwise any references to it would fail. This is not the same as providing it at run time.

Related

Component testing classes that use OptaPlanner

I have a component that, amongst other things, makes use of OptaPlanner. We use junit for component/integration testing and I am having trouble with bean creation when running tests.
When running my test I get the following error...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.optaplanner.core.api.solver.SolverManager<com.company.uk.product.aepe.service.optaplanner.EngagementSolution, java.util.UUID>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1714)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1270)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1224)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
I use optaplanner-spring-boot-starter which normally created a SolveManager bean which is #Autowired'd into my classes, but not when run as a test.
My pom dependencies (sanitized for security reasons)....
<dependencies>
<!-- Actuator Dependencies START -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<!-- Actuator Dependencies END -->
<!-- Spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
...
<!-- Test Depemdencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.database-rider</groupId>
<artifactId>rider-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Required by Intellij to run Junit 5 tests -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
This thread suggests manually creating the SolverManager bean in a configuration class but also warn off doing this...
What is the 'best' way of ensuring thsi ben is available in my integration tests?
When I take the spring school timetabling quickstart of optaplanner-quickstarts and add the SolverManager autowired field in this unit test, it works:
#SpringBootTest(properties = {
"optaplanner.solver.termination.spent-limit=1h", // Effectively disable this termination in favor of the best-score-limit
"optaplanner.solver.termination.best-score-limit=0hard/*soft"})
public class TimeTableControllerTest {
#Autowired
private TimeTableController timeTableController;
#Autowired
private SolverManager<TimeTable, Long> solverManager;
#Test
#Timeout(600_000)
public void solveDemoDataUntilFeasible() throws InterruptedException {
assertNotNull(solverManager);
...
}
}
Also, there's test coverage for this in optaplanner repo itself, in org.optaplanner.spring.boot.autoconfigure.OptaPlannerAutoConfigurationTest#singletonSolverFactory.
Maybe in your case there's a problem with the generic types? Try autowiring without the generic types first. Let us know here if that was the problem.

Mocking a spring interface

I have a service with an #Autowired repository that I would like to mock with PowerMock. It is ofcourse quite easy to just create the mock, but the problem is injecting it.
My testcase must start 2 different servers so I run code like this:
new SpringApplicationBuilder(Server.class)
.profiles("test")
.properties("server.port=" + port)
.run();
And so I don't really have a reference to the repository that I want to replace with a mock one, and thus a Whitebox solution probably doesn't work.
I've tried doing something like this
Queue mockQueue = mock(Queue.class);
whenNew(Queue.class).withAnyArguments().thenReturn(mockQueue);
but since the Queue is an interface this doesn't really work. And I have no implementation to go mock either.
So I am kind of stuck here, and am wondering if this can be done and how?
For reference this is the repository
#Repository
public interface Queue extends JpaRepository<QueueItem, Long> {
...
}
for the sake of it I tried spying on the containing class like this:
QueueService queueService = spy(new QueueService());
whenNew(QueueService.class).withAnyArguments().thenReturn(queueService);
and then set the internal state:
Whitebox.setInternalState(queueService, "queue", mockQueue);
And this works if I create a new QueueService from the test, but if I run normaly then the QueueService will not be a spied object
Oh an my test class is currently annotated like this:
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringRunner.class)
#PrepareForTest(QueueService.class)
All the dependencies that I have:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-spring-web-autoconfigure</artifactId>
<version>0.0.13</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectreactor</groupId>
<artifactId>reactor-spring</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
<scope>test</scope>
Also quite interesting is that the class is loaded by a MockClassLoader

mvc:annotation-driven doesnt solve 406 error

I am trying to write a Junit test case for Spring and after a lot of reading I got everything working for a method that returns text/plain. When I tried to return application/json I ran into issues.
The consensus on SO seems to be: use mvc:annotation-driven. I tried this (by creating spring-web-servlet.xml shown below according to here. That didn't solve my issue however. Anyone know what I'm still doing wrong?
spring-web-servlet.xml (in WEB-INF folder)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven />
</beans>
The method in question (in class HelloService)
#GET
#RequestMapping("/json2")
#Produces({"application/json"})
#ResponseBody
public Object getUserInfoJSON(#RequestParam(value="p",defaultValue="0") Integer userId){
try (Connection conn = conn()) {
String query = "SELECT * FROM pulse.customer WHERE userId = ?";
PreparedStatement preparedStmt = conn.prepareStatement(query);
preparedStmt.setInt(1, userId);
ResultSet rs=preparedStmt.executeQuery();
if(rs.next())
return Json.createObjectBuilder().add("login name", rs.getString("loginName"));
return Json.createObjectBuilder().add("login name", "shit broke yo!!!");
}
catch(SQLException s){
return "sql exception:"+s.toString();
}
catch (NoResultException nre) {
//throw new UserNotFoundException(userId);
return "UserNotFoundException";
} catch (PersistenceException e) {
//throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
return "WebApplicationException";
}
}
The Junit test method (the version that takes in String works perfectly)
#Test
public void testUserInfoResponseJSON() throws Exception{
MvcResult result=mockMvc.perform(get("/helloservice/json2?p=103")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith("application/json"))
.andReturn();
String content = result.getResponse().getContentAsString();
assertNotNull(content,"{login name:jbray}");
}
If needed, heres my pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
</dependency>
<!-- Adding RESTEasy support to Bean Validations -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-validator-provider-11</artifactId>
<version>3.1.4.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-links -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-links</artifactId>
<version>3.1.4.Final</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<!--SPRING-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.paypal.springboot</groupId>
<artifactId>resteasy-spring-boot-starter</artifactId>
<version>2.3.3-RELEASE</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--JUNIT-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.0.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.1.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
I saw your dependency and your code in detail and found that you are using Glassfish's provider implementation of the JSR 353. those classes are org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl, org.glassfish.json.JsonStringImpl, and org.glassfish.json.JsonNumberImpl, and javax.json.JsonValue$3 (an anonymous class for the value FALSE).
You need to change below code
return Json.createObjectBuilder().add("login name", rs.getString("loginName"));
return Json.createObjectBuilder().add("login name", "shit broke yo!!!");
to
return Json.createObjectBuilder().add("login name", rs.getString("loginName")).build().toString();
return Json.createObjectBuilder().add("login name", "shit broke yo!!!").build().toString();
and change return type of to getUserInfoJSON() method to String. Detailed explanation of JSR 353 classes and it mapping to ObjectMapper is available at https://stackoverflow.com/a/19205116/3530898

Spring Integration JDBC Insert Statement

I'm new to Spring integration. I'm trying to write a POJO for my database. I'm getting this error, which I don't quite understand. Is my syntax wrong, or am I using channels/adapters/gateways in the wrong manner?
no declaration can be found for element int-jdbc:outbound-channel-adapter.
Here is my code:
<?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:integration="http://www.springframework.org/schema/integration"
xmlns:file="http://www.springframework.org/schema/integration/file"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
xmlns:util="http://www.springframework.org/schema/util" xmlns:int-ftp="http://www.springframework.org/schema/integration/ftp"
xsi:schemaLocation="http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<int-jdbc:outbound-gateway id="transmissionGateway"
query="insert into MSRB_RTRS (Sec_ID, SourceLoad_ID, TradeDate) values (:Sec_ID,
:SourceLoad_ID, :TradeDate)"
data-source="rmsa">
</int-jdbc:outbound-gateway>
public interface DatabaseService {
public void insertMessage(int secID, int sourceLoadID, String tradeDate);
}
#Inject
DatabaseService service;
service.insertMessage(-1, -1, "20170830");
Here are my dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>
<version>4.3.5.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.0.8112.100</version>
</dependency>
<dependency>
<groupId>com.companyname</groupId>
<artifactId>spring-boot-common</artifactId>
<version>1.0.0.COMMON-SBCOMMON-14</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<!-- End -->
<dependency>
<groupId>com.companyname</groupId>
<artifactId>companyname-spring-core-spring-4</artifactId>
<version>1.1-M20160505-01</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.5</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
The spring integration jdbc pom contains
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>4.3.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
spring-integration-jdbc-2.2.xsd
Don't put a version on the schema import. It has to match the version you are using (4.3).
If you leave the version off, Spring will resolve the right version for you (see /META-INF/spring.schemas in the jar).
http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
In any case; everything (jars, schema) must have matching versions.

Katharsis in combination with Spring Boot

I have implemented a REST API using Spring Boot (version 1.3.6.RELEASE), which is working as expected. However I would like to add JSON API support to my application.
The problem is that I get a 404 when trying to execute a GET on a Katharsis resource.
The dependencies in pom.xml look as follows (I use Spring Security too):
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
<!--SpringFox dependencies -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-tools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>dumbster</groupId>
<artifactId>dumbster</artifactId>
<version>1.6</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.katharsis</groupId>
<artifactId>katharsis-spring</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.9</version>
</dependency>
</dependencies>
My application initialisation class is as follows:
#SpringBootApplication
#Configuration
#EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class)
#EnableSwagger2
#ComponentScan(basePackages = "com.myapp")
#Import({KatharsisConfigV2.class})
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
The resource class:
#ApiModel(description = "")
#JsonApiResource(type = "foo-data")
public class FooData extends DomainRepresentation {
#JsonApiId
private String id = null;
#JsonProperty
private String name = null;
// .... getters & setters
}
ResourceRepository class:
#JsonApiResourceRepository(FooData.class)
#Component
public class FooDataKatApi extends MyApi {
#Autowired
private FooDataService fooDataService;
#JsonApiFindOne
public FooData foodataIdGet(String id, QueryParams requestParams) {
FooData result = fooDataService.getFooDataById(id);
return result;
}
}
If I add Spring #ResourceMappings than I get data back but without Katharsis additions like "link", etc. It's as if the API call is not being picked up by Katharsis, but it's handled by Spring.
Any help would be appreciated.
-- EDITTED --
The FooDataService is as follows:
#Service
public class FooDataService extends MyService {
#Autowired
private FooDataRepository fooDataRepository;
public FooData getFooDataById(String id) {
FooDataEnt fooDataEnt = fooDataRepository.findByFooDataId(id);
if (fooDataEnt != null) {
return convertFooDataEntToFooData.apply(fooDataEnt);
}
throw new NotFoundException("Foo not found");
}
}
The FooDataRepository extends Spring's PagingAndSortingRepository.
Katharsis config in application.yaml:
katharsis:
resourcePackage: com.my.package
domainName: http://localhost:8080
pathPrefix: /api/kat
The request and response from PostMan
-- UPDATE 1 --
Apparently the configured value for katharsis.pathPrefix was not correct. Web application's context-root is "/api" and the value of katharsis.pathPrefix should be only "/kat".
My next problem is that a RepositoryNotFoundException is being throw while handling the request, while the Resource class is found already.
I don't see your foo data service implementation anywhere. However, I am 99% sure you're not passing the json api accept type.
Accept: application/vnd.api+json
I solved the riddle by debugging the code and finding out that my Katharsis config was not correct. Katharsis only picked up the resource classes but not the resource repository classes. When I changed the katharsis.resourcePackage to a higher level where the resource repositories resided, the problem got solved and Katharsis picked up all related annotated classes.

Categories