@Path("/abc")
@Produces(MediaType.APPLICATION_JSON)
public class ABCController
{
@Autowired
private MyService myService;
@GET
public Response getSome(@QueryParam("identification") List<String> ids)
{
GenericEntity<List<Label>> entity = new GenericEntity<>(myService.findSomething(ids))
{
};
return Response.ok(entity).build();
}
MyService:
@RequiredArgsConstructor
@Service
public class MyService
{
private final MyMapper myMapper;
private final JpaRepository myRepository;
public List<String> findSomething(ids){
myRepository.findXYZ(ids);
}
My MainClass:
@SpringBootApplication
public class MainClass
{
public static void main(String[] args)
{
SpringApplication.run(MainClass.class, args);
}
@Bean
public MyMapper myMapper()
{
return new MyMapperImpl();
}
}
build.gradle:
buildscript {
ext {
LOMBOK_VERSION = "1.18.22"
SPRING_BOOT_VERSION = "2.6.6"
JERSEY_VERSION = "3.0.8"
JACKSON_VERSION = "2.13.1"
MSSQL_JDBC_VERSION = "9.4.1.jre11"
MAPSTRUCT = "1.5.1.Final"
}
}
plugins {
id "org.gretty" version "4.0.3"
}
apply plugin: 'java-library'
apply plugin: 'java'
apply plugin: 'war'
repositories {
mavenLocal()
maven {
url = '...'
}
}
dependencies {
compileOnly "org.projectlombok:lombok:${LOMBOK_VERSION}"
testImplementation "org.projectlombok:lombok:${LOMBOK_VERSION}"
annotationProcessor "org.projectlombok:lombok:${LOMBOK_VERSION}"
implementation "org.mapstruct:mapstruct:${MAPSTRUCT}"
annotationProcessor "org.mapstruct:mapstruct-processor:${MAPSTRUCT}"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:${SPRING_BOOT_VERSION}"
implementation "com.microsoft.sqlserver:mssql-jdbc:${MSSQL_JDBC_VERSION}"
implementation "org.glassfish.jersey.containers:jersey-container-servlet-core:${JERSEY_VERSION}"
implementation "org.glassfish.jersey.inject:jersey-hk2:${JERSEY_VERSION}"
implementation "org.glassfish.jersey.media:jersey-media-json-jackson:${JERSEY_VERSION}"
}
When i call http://localhost:8080/myservice/abc?identification=61234561234569,71234561234568,71234561234569
i got a NullPointerException
of myService.findSomething(ids)
I start the application with gradle command appRun
CodePudding user response:
Though spring brings his own "framework for REST-Service development"(spring-web), there should be no reason, why JAX-RS could not use spring-core and even spring-boot.
The problem (for that particular NPE) is:
For auto-wiring: both (wired & wiring) objects need to be "spring managed (beans)"! ;) In MyService this is achieved with @Service annotation.
To fix the problem, we need to participate ABCController in spring context as well!
"Least intrusive"/simplest approach - to annotate ABCController
with @Component
:
...
import org.springframework.stereotype.Component;
@Component // !
@Path("/abc")
@Produces(MediaType.APPLICATION_JSON)
public class ABCController ...
This ( correct "component scan") will "lift" ABCController into spring context and enable auto-wiring (from/to) that object.
Another approach, decoupling the "implementations" from spring:
For this we need to remove all (possible) org.springframework.*
imports from our "spring-independent" classes. (Of course it is not possible in very spring specific classes (spring-web(Rest)Controllers,Spring-data-repos, ...).
- To replace
@Component/Service/Repository
annotations, we move the instantiations to@Bean
annotated methods to our spring configuration(class(es)) (..see MyMapper bean!) - To replace
@Autowired
we'd have to "manually wire" them or use "implicit constructor auto wire" (within the mentioned@Bean
methods)
So your Config(/SpringBootApp), could look like:
@SpringBootApplication
public class MainClass
{
public static void main(String[] args)
{
SpringApplication.run(MainClass.class, args);
}
@Bean
public MyMapper myMapper()
{
return new MyMapperImpl();
}
@Bean // singleton is default "scope"!!...
public MyService myService(/*implicitly @Autowired :*/ JPARepository repo, MyMapper mapper /* ..and taken care (hopefully;) by spring*/) {
return new MyService(mapper, repo);
}
// and:
@Bean
public ABCController abcController(/*implicitly @Autowired :*/ MyService service /* ..and taken care (hopefully;) by spring*/) {
ABCController bean = new ABCController();
bean.setMyService(service);
return bean;
}
}
With the according adjustments to ABCController:
@Path("/abc")
@Produces(MediaType.APPLICATION_JSON)
public class ABCController
{
// NOT @Autowired
private MyService myService;
...
// Setter(/getter) for myService !
CodePudding user response:
The are a dependency for jersey in spring-boot: spring-boot-starter-jersey
The build.gradle looks like this:
buildscript {
ext {
LOMBOK_VERSION = "1.18.22"
SPRING_BOOT_VERSION = "2.6.6"
JERSEY_VERSION = "3.0.8"
JACKSON_VERSION = "2.13.1"
MSSQL_JDBC_VERSION = "9.4.1.jre11"
MAPSTRUCT = "1.5.1.Final"
}
}
apply plugin: 'java-library'
apply plugin: 'java'
apply plugin: 'war'
repositories {
mavenLocal()
maven {
...
}
}
dependencies {
compileOnly "org.projectlombok:lombok:${LOMBOK_VERSION}"
testImplementation "org.projectlombok:lombok:${LOMBOK_VERSION}"
annotationProcessor "org.projectlombok:lombok:${LOMBOK_VERSION}"
implementation "org.mapstruct:mapstruct:${MAPSTRUCT}"
annotationProcessor "org.mapstruct:mapstruct-processor:${MAPSTRUCT}"
implementation "org.springframework.boot:spring-boot-starter-jersey:${SPRING_BOOT_VERSION}"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:${SPRING_BOOT_VERSION}"
implementation "com.microsoft.sqlserver:mssql-jdbc:${MSSQL_JDBC_VERSION}"
}
The controller becomes the @Component
@Path("/abc")
@Produces(MediaType.APPLICATION_JSON)
@Component
public class ABCController
{
@Autowired
private MyService myService;
@GET
public Response getSome(@QueryParam("identification") List<String> ids)
{
GenericEntity<List<Label>> entity = new GenericEntity<>(myService.findSomething(ids))
{
};
return Response.ok(entity).build();
}
The MainClass is servlet:
@SpringBootApplication
public class MainClass extends SpringBootServletInitializer
{
public static void main(String[] args)
{
new MainClass().configure(new SpringApplicationBuilder(MainClass.class)).run(args);
}
@Bean
public MyMapper myMapper()
{
return new MyMapperImpl();
}
}
MyService is a @Service
@RequiredArgsConstructor
@Service
public class MyService
{
I added a JerseyConfig:
@Component
public class JerseyConfig extends ResourceConfig
{
public JerseyConfig()
{
register(ABCController.class);
}
}