Feign Client couldn't find custom registered eureka service - spring-boot

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

This has been fixed by just setting virtual host name.
newInstanceConfig.setVirtualHostname(workflowEngineApplicationName);

Related

ClassPath resource can not be accessed in Docker Spring

I have a userService file which includes this code:
package com.example.demo.services;
import com.example.demo.entity.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
#Service
public class UserService {
public static AtomicReference<UserService> INSTANCE = new AtomicReference<UserService>();
public static List<User> userList ;
public UserService() throws IOException {
final UserService previous = INSTANCE.getAndSet(this);
userList = new ObjectMapper().readValue(
new ClassPathResource("db/user.json").getFile(),
new ObjectMapper().getTypeFactory().constructCollectionType(List.class, User.class));
if(previous != null)
throw new IllegalStateException("Second singleton " + this + " created after " + previous);
}
public static UserService getInstance() {
return INSTANCE.get();
}
}
In this Service I am loading a JSON file into the variable userList and the JSON file is stored in src/main/resources/db/user.json. This works fine in the IDE. But when I creates a Jar file either via Intellij or manually, the db/user.json is stored in BOOT-INF/classes/db/user.json (inspected via this command: jar tf backend.jar).
The Docker Image could not get started as it could not find the file. So how would I change this so that it should work both in normal debug and Docker image?
To be noted, userList converts the JSON file in the List.

Spring Boot CXF service throws an exception with JPA

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

Spring Boot REST with Hadoop HBASE

I'm looking to build an simple RESTFull API to access into HBase.
I looked Python HappyBase, but my cluster is kerberised. Now I'm into Spring.
I used to make simple API REST with Solr Cloud and Spring Boot.
Is it possible to do same with Hbase ?
I have no idea if I have to use Spring Boot 'Yarn App'
=> https://spring.io/guides/gs/yarn-basic/
Or Spring Hadoop.
=> https://projects.spring.io/spring-hadoop/
Just want a really simple API.
Thanks for help.
I wrote a simple demo project for using hbase in spring boot restful application without xml.
This demo mainly depends spring-data-hadoop and hbase-client.
gradle dependencies:
compile('org.springframework.boot:spring-boot-starter-data-rest')
compile('org.springframework.boot:spring-boot-starter-web')
compile 'org.springframework.data:spring-data-hadoop:2.5.0.RELEASE'
compile('org.apache.hbase:hbase-client:1.3.1'){
exclude group :'log4j',module:'log4j'
exclude group :'org.slf4j',module:'slf4j-log4j12'
exclude group: 'javax.servlet', module: 'servlet-api'
}
compile('org.springframework.boot:spring-boot-configuration-processor')
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
Configure the hbase connection parameters in spring boot's application.properties (No XML!):
spring.data.hbase.zkQuorum=192.168.0.109:2181
spring.data.hbase.zkBasePath=/hbase
spring.data.hbase.rootDir=file:///home/hbase-1.2.2
class HbaseProperties.java:
#ConfigurationProperties(prefix = "spring.data.hbase")
public class HbaseProperties {
// Addresses of all registered ZK servers.
private String zkQuorum;
// Location of HBase home directory
private String rootDir;
// Root node of this cluster in ZK.
private String zkBasePath;
// getters and setters...
}
HbaseConfig.java, inject the configurations into the HbaseTemplate:
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.hadoop.hbase.HbaseTemplate;
#Configuration
#EnableConfigurationProperties(HbaseProperties.class)
public class HbaseConfig {
#Autowired
private HbaseProperties hbaseProperties;
#Bean
public HbaseTemplate hbaseTemplate() {
org.apache.hadoop.conf.Configuration configuration = HBaseConfiguration.create();
configuration.set("hbase.zookeeper.quorum", this.hbaseProperties.getZkQuorum());
configuration.set("hbase.rootdir", this.hbaseProperties.getRootDir());
configuration.set("zookeeper.znode.parent", this.hbaseProperties.getZkBasePath());
return new HbaseTemplate(configuration);
}
}
Service class, we can use the configured HbaseTemplate now:
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.hadoop.hbase.HbaseTemplate;
import org.springframework.stereotype.Service;
import com.zql.hbasedemo.vo.Quote;
#Service
public class FeedService {
#Autowired
private HbaseTemplate hbaseTemplate;
#PostConstruct
public void test(){
Quote quote = new Quote();
quote.setEventType("ft");
quote.setHandicap("4");
quote.setMarket("OU");
quote.setMatchId("27350208");
quote.setSelection("OVER");
quote.setPrice("1.93");
saveQuote(quote);
}
public Quote saveQuote(Quote quote) {
hbaseTemplate.put("quotes", quote.getMatchId(), "data", quote.getMarket() + ":" + quote.getSelection(),
quote.getPrice().getBytes());
return quote;
}
}
Rest Controller.
#RestController
public class FeedController {
#Autowired
private FeedService feedService;
#SuppressWarnings({ "unchecked", "rawtypes" })
#PostMapping(value = "/feed/quote", consumes = "application/json", produces = "application/json")
public ResponseEntity<Quote> saveQuote(#RequestBody Quote quote) {
Quote result = feedService.saveQuote(quote);
return new ResponseEntity(result, new HttpHeaders(), HttpStatus.OK);
}
}

Exporting Spring Boot Actuator Metrics (& Dropwizard Metrics) to Statsd

I'm trying to export all of the metrics which are visible at the endpoint /metrics to a StatsdMetricWriter.
I've got the following configuration class so far:
package com.tonyghita.metricsdriven.service.config;
import com.codahale.metrics.MetricRegistry;
import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.ExportMetricReader;
import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.boot.actuate.metrics.reader.MetricRegistryMetricReader;
import org.springframework.boot.actuate.metrics.statsd.StatsdMetricWriter;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableMetrics(proxyTargetClass = true)
public class MetricsConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(MetricsConfig.class);
#Value("${statsd.host:localhost}")
private String host = "localhost";
#Value("${statsd.port:8125}")
private int port;
#Autowired
private MetricRegistry metricRegistry;
#Bean
#ExportMetricReader
public MetricReader metricReader() {
return new MetricRegistryMetricReader(metricRegistry);
}
#Bean
#ExportMetricWriter
public MetricWriter metricWriter() {
LOGGER.info("Configuring StatsdMetricWriter to export to {}:{}", host, port);
return new StatsdMetricWriter(host, port);
}
}
Which writes all of the metrics which I've added to Statsd, but I'd like to also send the system/JVM metrics that are visible on the /metrics endpoint.
What am I missing?
I had the same problem and found a solution here: https://github.com/tzolov/export-metrics-example
Just add a MetricsEndpointMetricReader to your config and everything available at th e/metrics endpoint will be published to the StatsdMetricWriter.
Here is a complete example config for spring boot 1.3.x and dropwizard metrics-jvm 3.1.x:
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.jvm.GarbageCollectorMetricSet;
import com.codahale.metrics.jvm.MemoryUsageGaugeSet;
import com.codahale.metrics.jvm.ThreadStatesGaugeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter;
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
import org.springframework.boot.actuate.endpoint.MetricsEndpointMetricReader;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.statsd.StatsdMetricWriter;
import org.springframework.boot.actuate.metrics.writer.Delta;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class MetricsConfiguration {
#Bean
public MetricRegistry metricRegistry() {
final MetricRegistry metricRegistry = new MetricRegistry();
metricRegistry.register("jvm.memory",new MemoryUsageGaugeSet());
metricRegistry.register("jvm.thread-states",new ThreadStatesGaugeSet());
metricRegistry.register("jvm.garbage-collector",new GarbageCollectorMetricSet());
return metricRegistry;
}
/*
* Reading all metrics that appear on the /metrics endpoint to expose them to metrics writer beans.
*/
#Bean
public MetricsEndpointMetricReader metricsEndpointMetricReader(final MetricsEndpoint metricsEndpoint) {
return new MetricsEndpointMetricReader(metricsEndpoint);
}
#Bean
#ConditionalOnProperty(prefix = "statsd", name = {"prefix", "host", "port"})
#ExportMetricWriter
public MetricWriter statsdMetricWriter(#Value("${statsd.prefix}") String statsdPrefix,
#Value("${statsd.host}") String statsdHost,
#Value("${statsd.port}") int statsdPort) {
return new StatsdMetricWriter(statsdPrefix, statsdHost, statsdPort);
}
}
From what I've seen in spring-boot code, only calls to CounterService and GaugeService implementations are forwarded to dropwizard's MetricRegistry.
Therefore, as you already observed, only counter.* and gauge.* metrics from the /metrics endpoint will end up in Statsd.
System and JVM metrics are exposed through custom SystemPublicMetrics class, which doesn't use counter or gauge service.
I'm not sure if there is a simpler solution (maybe someone from Spring team will comment), but one way to do it (not spring-boot specific) would be to use a scheduled task that periodically writes system stats to the MetricRegistry.
To register JVM metrics you can use the JVM related MetricSets supplied by codehale.metrics.jvm library. You can just add the whole set without supplying whether they are gauges or counters.
Here is my example code where I am registering jvm related metrics:
#Configuration
#EnableMetrics(proxyTargetClass = true)
public class MetricsConfig {
#Autowired
private StatsdProperties statsdProperties;
#Autowired
private MetricsEndpoint metricsEndpoint;
#Autowired
private DataSourcePublicMetrics dataSourcePublicMetrics;
#Bean
#ExportMetricReader
public MetricReader metricReader() {
return new MetricRegistryMetricReader(metricRegistry());
}
public MetricRegistry metricRegistry() {
final MetricRegistry metricRegistry = new MetricRegistry();
//jvm metrics
metricRegistry.register("jvm.gc",new GarbageCollectorMetricSet());
metricRegistry.register("jvm.mem",new MemoryUsageGaugeSet());
metricRegistry.register("jvm.thread-states",new ThreadStatesGaugeSet());
return metricRegistry;
}
#Bean
#ConditionalOnProperty(prefix = "metrics.writer.statsd", name = {"host", "port"})
#ExportMetricWriter
public MetricWriter statsdMetricWriter() {
return new StatsdMetricWriter(
statsdProperties.getPrefix(),
statsdProperties.getHost(),
statsdProperties.getPort()
);
}
}
Note: I am using spring boot version 1.3.0.M4
Enjoy! (see the public metrics logged in console as dropwizard metrics)
#Configuration
#EnableMetrics
#EnableScheduling
public class MetricsReporter extends MetricsConfigurerAdapter {
#Autowired private SystemPublicMetrics systemPublicMetrics;
private MetricRegistry metricRegistry;
#Scheduled(fixedDelay = 5000)
void exportPublicMetrics() {
for (Metric<?> metric : systemPublicMetrics.metrics()) {
Counter counter = metricRegistry.counter(metric.getName());
counter.dec(counter.getCount());
counter.inc(Double.valueOf(metric.getValue().toString()).longValue());
}
}
#Override
public void configureReporters(MetricRegistry metricRegistry) {
this.metricRegistry = metricRegistry;
ConsoleReporter.forRegistry(metricRegistry).build().start(10, TimeUnit.SECONDS);
}
}

#Autowired not working on jersey resource

workflowService is null. The bean configuration is correct because manual injection works fine in other portions of the application.
Here's my resource:
#Path("/workflowProcess")
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public class WorkflowProcessResource {
#Autowired
WorkflowService workflowService;
#Autowired
WorkflowProcessService workflowProcessService;
#GET
#Path ("/getWorkflowProcesses/{uuid}")
public Collection<WorkflowProcessEntity> getWorkflows (#PathParam("uuid") String uuid) {
WorkflowEntity workflowEntity = workflowService.findByUUID(uuid);
return workflowEntity.getWorkflowProcesses();
}
}
From what I keep finding on Google on sites like http://www.mkyong.com/webservices/jax-rs/jersey-spring-integration-example/, it looks like ContextLoaderListener is the key. But I've already added that to the application context.
import com.sun.jersey.spi.container.servlet.ServletContainer;
import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
import org.atmosphere.cpr.AtmosphereFramework;
import org.atmosphere.cpr.AtmosphereServlet;
import org.atmosphere.handler.ReflectorServletProcessor;
import org.glassfish.grizzly.servlet.ServletRegistration;
import org.glassfish.grizzly.servlet.WebappContext;
import org.glassfish.grizzly.websockets.WebSocketAddOn;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import java.io.IOException;
import java.util.logging.Logger;
public class Main {
protected static final Logger logger = Logger.getLogger(Main.class.getName());
public static void main(String[] args) throws IOException {
logger.info("Starting server...");
final HttpServer server = HttpServer.createSimpleServer(".", 8181);
WebappContext ctx = new WebappContext("Socket", "/");
//enable annotation configuration
ctx.addContextInitParameter("contextClass", "org.springframework.web.context.support.AnnotationConfigWebApplicationContext");
ctx.addContextInitParameter("contextConfigLocation", "com.production");
//allow spring to do all of it's stuff
ctx.addListener("org.springframework.web.context.ContextLoaderListener");
//add jersey servlet support
ServletRegistration jerseyServletRegistration = ctx.addServlet("JerseyServlet", new SpringServlet());
jerseyServletRegistration.setInitParameter("com.sun.jersey.config.property.packages", "com.production.resource");
jerseyServletRegistration.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", "com.production.resource.ResponseCorsFilter");
jerseyServletRegistration.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
jerseyServletRegistration.setLoadOnStartup(1);
jerseyServletRegistration.addMapping("/api/*");
What you need here, I think, is #InjectParam instead of #Autowired
#InjectParam worked fine instead of #Autowired, with a slight change
#InjectParam cannot be applied to the constructor itself hence has to be applied to the arguments to the constructor.
public OrderService(#InjectParam OrderValidationService service,
#InjectParam OrderCampaignService campaignService) {
this.service = service;
this.submissionErrorHandler = submissionErrorHandler;
this.campaignService = campaignService;
}

Resources