I would like to create a custom autoconfig in external library which is a feign client interface
But when I point the auto configuration by
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.hello.world.MyFeginClient
When I build my springBoot, I am failed to initiate the service
Failed to instantiate : Specified class is an interface
If I want to put my fegin client in my autoconfiguarion, what should I do? Thanks
Make sure you have this dependency added in your pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Also you need to add this annotation #EnableFeignClients which scans for the #FeignClient
#EnableFeignClients
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication .class, args);
}
}
Related
I want to try out microservices using 2.5.4 spring boot and getting problems in discovery
Steps:
Created a RestTemplate with #LoadBalanced, and trying to call the service using "application name in the url"
I have the register and fetch registry true in properties (thought this should get available services?)
Error: No such host is known
I am trying
#Autowired
private DiscoveryClient discoveryClient;
and do
discoveryClient.getInstances("myappservice-name").forEach((ServiceInstance s) -> {
System.out.println(ToStringBuilder.reflectionToString(s));
});
But all examples tell to use an endpoint? or commandLineRunner. Both I'm looking for auto loading
https://spring.io/guides/gs/service-registration-and-discovery/
https://spring.io/blog/2015/01/20/microservice-registration-and-discovery-with-spring-cloud-and-netflix-s-eureka
Not ok to call the below for each app
#RequestMapping("/service-instances/{applicationName}") public
List<ServiceInstance> serviceInstancesByApplicationName(
How can I register automatically?
EDIT: More detailed question
(1) SERVICE App
bootstrap - spring.application.name=pluralsight-toll-service
application props
server.port=0
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.instance-id=${spring.application.name}:${random.int}
eureka.instance.hostname=localhost
management.endpoints.web.exposure.include=*
App
#SpringBootApplication
#EnableEurekaClient
public class PluralsightEurekaTollrateServiceApplication {
I see app registered in eureka server
(2) Client
bootstrap
spring.application.name=pluralsight-tollrate-billboard
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
application.props
server.port=8081
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
management.endpoints.web.exposure.include=*
App
#SpringBootApplication
#EnableEurekaClient
#EnableDiscoveryClient
public class PluralsightEurekaTollrateBillboardApplication {
Controller
#LoadBalanced
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
#Autowired
RestTemplate restTemplate;
#RequestMapping("/dashboard")
public String GetTollRate(#RequestParam int stationId, Model m) {
TollRate tr = restTemplate.getForObject("http://pluralsight-toll-service/tollrate/" + stationId, TollRate.class);
Error: pluralsight-toll-service host is unknown
How can call service from client using the name
Fixed the issue
Its all down to client project dependencies
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
<version>3.0.3</version>
</dependency> -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
The names are too close
spring-cloud-netflix-eureka-client is wrong
spring-cloud-starter-netflix-eureka-client is the right one
Because of the wrong one, I had to add eureka-client of com.netflix.eureka. Cleaned all and it works
(Also I was missing spring-cloud , as I was creating from eclipse. In future will use initializ only )
I'm using SpringBoot2, Spring5 in my Java micro service application. I have required dependencies including the Scheduler. Build is fine without any compilation error but during run time, I'm getting below error in PooledAsyncRunner:-
***************************** APPLICATION FAILED TO START
*************************** Description: Parameter 0 of constructor in com.connector.async.core.PooledAsyncRunner required a bean of type
'reactor.core.scheduler.Scheduler' that could not be found. Action:
Consider defining a bean of type 'reactor.core.scheduler.Scheduler' in
your configuration.
#Service
public class PooledAsyncRunner implements AsyncRunner {
private final Scheduler scheduler;
#Autowired
public PooledAsyncRunner(Scheduler scheduler) {
this.scheduler = scheduler;
}
}
Below is spring main application file where I have explicitly annotated auto-configuration:-
#SpringBootApplication
#EnableAutoConfiguration
public class MarketApplication {
}
I have reactor-core dependency as well in pom.xml.
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.1.8.RELEASE</version>
</dependency>
Please advise. Thanks
For my spring boot application I use annotation based configuration and a WebApplicationInitalizer.
One of my dependencies provides a spring configuration in an xml, included in the jar. I use #ImportResource to load the context xml. This seems to work, except for the fact that inside this xml, there are property placeholders, for example ${poolsize:10}
Apparently, spring does not automatically replace these placeholders (I get a NumberFormatException). Is there some extra configuration I need to add?
Our startup class:
public class Application implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
// config
rootContext.register(JmsConfiguration.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
}
}
And the configuration class (we use spring-jms):
#Configuration
#EnableJms
#ComponentScan(basePackages = { "..." })
public class JmsConfiguration implements JmsListenerConfigurer {
// config for jms listener and jaxb, nothing to do with property handling
}
Perhaps I'm mistaken in thinking that using a WebapplicationInitializer is how to use spring boot. Perhaps we don't even need spring boot? The only spring boot related dependency we use is:
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Spring dependencies we use:
org.springframework:spring-context:jar:4.3.8.RELEASE:compile
org.springframework:spring-jms:jar:4.3.8.RELEASE:compile
org.springframework:spring-oxm:jar:4.3.8.RELEASE:compile
org.springframework:spring-context:jar:4.3.8.RELEASE:compile
org.springframework:spring-beans:jar:4.3.8.RELEASE:compile
I figured it out thanks #M. Deinum
We don't need spring boot to use the WebApplicationInitializer, but (at least without spring boot) we have to declare our own PropertySourcesPlaceholderConfigurer:
#Configuration
#ImportResource(locations = {"classpath*:/library-context.xml"})
public class MyConfiguration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
NB. This works out of the box in spring boot thanks to #EnableAutoConfiguration and #PropertyPlaceholderAutoConfiguration which contains the exact same PropertySourcesPlaceholderConfigurer bean
I am looking for solution for distributed spring configuration. I am thinking of storing it in zookeeper. https://github.com/spring-cloud/spring-cloud-zookeeper does have that functionality but apparently it requires to use spring-boot.
Is there any similar library that I can use outside spring-boot
Consul by HashiCorp
Consul is a popular option because it is:
Open Source
Includes Service Discovery & Configuration
Support Multi-Datacenter out of the box
Etc.
It doesn't require you to use Spring Boot, it just provides the auto-configurations in case you do decide to go with Spring Boot. In other words, if you're not using Spring Boot, none of the configurations will apply automatically, you'll have to provide the configuration yourself.
Zookeeper is a good option, go for it.
EDIT:
To use Zookeeper without Spring Boot, you'd need to register the appropriate beans either manually or by importing the auto-configuration classes that Spring Boot would import for you implicitly. This rule of thumb generally applies to all Spring Boot-enabled modules.
In your case, you'd most likely need to import just the ZookeeperConfigBootstrapConfiguration and ZookeeperConfigAutoConfiguration. The classes are to be found within spring-cloud-zookeeper-config module so no Spring Boot dependencies needed.
Alternatively, you should look at those classes and their #Imports and declare the beans manually.
I found a solution for using spring-cloud-zookeeper without Spring Boot, based on the idea provided here https://wenku.baidu.com/view/493cf9eba300a6c30d229f49.html
First, create a CloudEnvironement class that will create a PropertySource from Zookeeper :
CloudEnvironement.java
public class CloudEnvironment extends StandardServletEnvironment {
#Override
protected void customizePropertySources(MutablePropertySources propertySources) {
super.customizePropertySources(propertySources);
try {
propertySources.addLast(initConfigServicePropertySourceLocator(this));
}
catch (Exception ex) {
logger.warn("failed to initialize cloud config environment", ex);
}
}
private PropertySource<?> initConfigServicePropertySourceLocator(Environment environment) {
ZookeeperConfigProperties configProp = new ZookeeperConfigProperties();
ZookeeperProperties props = new ZookeeperProperties();
props.setConnectString("myzookeeper:2181");
CuratorFramework fwk = curatorFramework(exponentialBackoffRetry(props), props);
ZookeeperPropertySourceLocator propertySourceLocator = new ZookeeperPropertySourceLocator(fwk, configProp);
PropertySource<?> source= propertySourceLocator.locate(environment);
return source ;
}
private CuratorFramework curatorFramework(RetryPolicy retryPolicy, ZookeeperProperties properties) {
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();
builder.connectString(properties.getConnectString());
CuratorFramework curator = builder.retryPolicy(retryPolicy).build();
curator.start();
try {
curator.blockUntilConnected(properties.getBlockUntilConnectedWait(), properties.getBlockUntilConnectedUnit());
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
return curator;
}
private RetryPolicy exponentialBackoffRetry(ZookeeperProperties properties) {
return new ExponentialBackoffRetry(properties.getBaseSleepTimeMs(),
properties.getMaxRetries(),
properties.getMaxSleepMs());
}
}
Then create a custom XmlWebApplicationContext class : it will enable to load the PropertySource from Zookeeper when your webapplication start and replace the bootsrap magic of Spring Boot:
MyConfigurableWebApplicationContext.java
public class MyConfigurableWebApplicationContext extends XmlWebApplicationContext {
#Override
protected ConfigurableEnvironment createEnvironment() {
return new CloudEnvironment();
}
}
Last, in your web.xml file add the following context-param for using your MyConfigurableWebApplicationContext class and bootstraping your CloudEnvironement.
<context-param>
<param-name>contextClass</param-name>
<param-value>com.kiabi.config.MyConfigurableWebApplicationContext</param-value>
</context-param>
If you use a standard property file configurer, it should still be loaded so you can have properties in both a local file and Zookeeper.
For all this to work you need to have spring-cloud-starter-zookeeper-config and curator-framework jar in your classpath with their dependancy, if you use maven you can add the following to your pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-zookeeper-dependencies</artifactId>
<version>1.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-config</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
</dependencies>
I'm trying to run simple Spring Data Rest Boot app (v1.2.3.RELEASE) with only one small modification from working Spring reference example app (http://spring.io/guides/gs/accessing-mongodb-data-rest/) and it failed to start.
To be more specific when I use:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
and just following simple code configuration:
public class Application {
public static void main(String[] args){
SpringApplication.run(Config.class, args);
}
}
#SpringBootApplication
public class Config {
}
without anything else I'm getting following error on startup:
2015-04-20 12:07:32.250 ERROR 5693 --- [ main]
o.s.boot.SpringApplication : Application startup failed
org.springframework.context.ApplicationContextException: Unable to
start embedded container; nested exception is
org.springframework.boot.context.embedded.EmbeddedServletContainerException:
Unable to start embedded Tomcat ...
Caused by:
java.lang.ClassCastException:
jug.ua.json.test.Config$$EnhancerBySpringCGLIB$$79797226 cannot be
cast to
org.springframework.data.rest.core.config.RepositoryRestConfiguration
at
org.springframework.boot.autoconfigure.data.rest.SpringBootRepositoryRestMvcConfiguration$$EnhancerBySpringCGLIB$$3a999d99.config()
...
However following code configuration is working fine:
#SpringBootApplication
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
Also if instead I use:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
separate Java config class approach is working fine as well...
What I'm doing wrong, cause I can't believe I spotted such an obvious bug?
Thank you,
Oleg
The problem appears to be due to a name clash between the config bean method on SpringBootRepositoryRestMvcConfiguration (inherited from Spring Data REST's RepositoryRestMvcConfiguration) and your configuration class named Config. Renaming it to something other than Config should get things working again.