Trying to write Eureka Client With Spring Cloud Netflix v1.2.0.Release
but facing the below mentioned issue. PFB code and configurations.
EurekaClient.java
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#Configuration
#EnableAutoConfiguration
#EnableEurekaClient
#RestController
#ComponentScan(basePackages={"com.west.eas.netflix.config"})
public class EurekaClient {
#RequestMapping("/")
public String home() {
return "Hello World";
}
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaClient.class).run(args);
}
}
application.yml
server:
port: 9000
spring:
application:
name: eas-eureka-client
eureka:
client:
healthcheck:
enabled: true
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
preferIpAddress: true
bootstrap.yml
spring:
application:
name: eu-client
cloud:
config:
uri: http://localhost:8888
encrypt:
failOnError: false
Client fails to start with following error
" Parameter 0 of method eurekaHealthIndicator in
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration$EurekaHealthIndicatorConfiguration
required a bean of type 'com.netflix.discovery.EurekaClient' that
could not be found."
the below screenshot will have more details on error stack
I even tried setting healthcheck enable to false in application.yml but it still wont work. Any Help would be appreciated.
Regards
The problem seems to be that you are naming your client EurekaClient, There is already a bean with that name. Rename that class to something else and it should work
as #spencergibb mentioned it did go wrong in adding dependencies, I've tried creating a new project via http://start.spring.io/ which resolved my issue.
Related
I'm using Eclipse 2020-03, Gradle and Tomcat. all I did follows.
Installing gradle through eclipse marketplace.
making gradle project.
adding those on build.gradle dependencies
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:28.2-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.27'
compile group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.27'
compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.4.0-b180830.0359'
compile group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: '2.27'
}
adding "rest" package on src/main/java
adding ApplicationConfig.java and RestApiService.java on rest package.
ApplicationConfig.java
package rest;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class ApplicationConfig extends Application {
#Override
public Map<String, Object> getProperties(){
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("jersey.config.server.provider.packages", "A_UnivG.rest");
return properties;
}
}
RestApiService.java
package rest;
import java.util.logging.Logger;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import Data.*;
#Path("/Data")
public class RestApiService {
Logger logger = Logger.getLogger("RestApiService");
IntegrationDAO dao = new IntegrationDAO();
#GET
#Path("hello")
#Produces(MediaType.TEXT_PLAIN)
public String getHello() {return "Hello";}
}
and when I try to request http://localhost:portnumber/A_UnivG/api/Data/hello it spits out only 404 error.
cannot figure out why.
My project works with plain jsp files. I have a JSP page which uses DAO Read but it works just fine. well, that shouldn't be a problem I just tried hello world and it doesn't work at all.
I am trying to use spring cloud gateway with kubernetes service discovery. Below is the setup which i am using
build.gradle
plugins {
id 'org.springframework.boot' version '2.2.0.BUILD-SNAPSHOT'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
}
ext {
set('springCloudVersion', "Hoxton.BUILD-SNAPSHOT")
set('springCloudKubernetesVersion', "1.0.3.RELEASE")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes'
implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-ribbon'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
mavenBom "org.springframework.cloud:spring-cloud-kubernetes-dependencies:${springCloudKubernetesVersion}"
}
}
test {
useJUnitPlatform()
}
application.yml
spring:
application.name: gateway
cloud:
gateway:
discovery:
locator:
enabled: true
kubernetes:
reload:
enabled: true
server:
port: 8080
logging:
level:
org.springframework.cloud.gateway: TRACE
org.springframework.cloud.loadbalancer: TRACE
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
enabled: true
info:
enabled: true
DemoApplication.java
package com.example.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
#SpringBootApplication
#EnableDiscoveryClient
#RestController
public class DemoApplication {
#Autowired
private DiscoveryClient discoveryClient;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#GetMapping("/services")
public List<String> services() {
return this.discoveryClient.getServices();
}
}
Spring cloud gateway is not able to redirect the request to other services. The log being printed is
2019-10-13 18:29:38.303 TRACE 1 --- [or-http-epoll-2]
o.s.c.g.f.WeightCalculatorWebFilter : Weights attr: {} 2019-10-13
18:29:38.305 TRACE 1 --- [or-http-epoll-2]
o.s.c.g.h.RoutePredicateHandlerMapping : No RouteDefinition found
for [Exchange: GET http://gateway-url/service-name/hello]
Although when I call http://<gateway-url>/services, then I can see the list of all services. So all the permission is being provided at pod level and service discovery is working fine. I am pretty sure there is some configuration, which i am missing but I am not able to figure it out even after looking at documentation several times.
So, it looks like there is an issue in Spring Cloud Hoxton.M3 release, as it's working fine with Hoxton.M2.
I have opened an issue for the same.
server
My stock-service client:
#Autowired
RestTemplate restTemplate;
ResponseEntity<List<String>> quoteResponse =
restTemplate.exchange("http://db-service/rest/db/" + userName,
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<String>>() {}
);
Here db-service is registered service in eureka server.
Its working if i hit directly like
/* ResponseEntity<List<String>> quoteResponse =
restTemplate.exchange("http://localhost:8300/rest/db/" + userName,
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<String>>() {}
);*/
#Configuration
public class Config {
#Bean
#LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
As far as I understand that db-service is your any micro-service and you want to send there request. You need to configure ribbon because RestTemplate doesn't understand db-service like host. You should add follow config:
db-service:
ribbon:
eureka:
enabled: false
listOfServers: localhost:8090
ServerListRefreshInterval: 15000
and maven dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
or you could add Discovery service(Eureka) to your system and you don't need to describing listOfSerevers because ribbon will get all information from discovery service
Please try by using spring-cloud-starter-netflix-eureka-client.
And check the version of spring-cloud-dependencies along with spring-boot-starter-parent version.
spring-cloud-starter-netflix-eureka-client should resolve the issue
I'm getting this exception :
Caused by: java.lang.IllegalStateException: Invalid mongo configuration, either uri or host/port/credentials must be specified
at org.springframework.boot.autoconfigure.mongo.MongoProperties.createMongoClient(MongoProperties.java:207)
at org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration.mongo(MongoAutoConfiguration.java:73)
at org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration$$EnhancerBySpringCGLIB$$15f9b896.CGLIB$mongo$1(<generated>)
at org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration$$EnhancerBySpringCGLIB$$15f9b896$$FastClassBySpringCGLIB$$c0338f6a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356)
at org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration$$EnhancerBySpringCGLIB$$15f9b896.mongo(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 25 common frames omitted
Here is my application.yml content :
spring:
data:
mongodb:
uri: mongodb://develop:d3VeL0p$#<my_host>:27017/SHAM
Here is my configuration class :
package com.me.service.testservice.config;
import com.mongodb.MongoClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
#Configuration
#EnableMongoRepositories(basePackages = {"com.me.service.testservice.repository"}, considerNestedRepositories = true)
public class SpringMongoConfiguration {
#Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(new MongoClient("<my_host>"), "SHAM");
}
}
Now I'm getting this stack trace when starting without failing, it looks like user develop doesn't have the right to connect:
Caused by: com.mongodb.MongoCommandException: Command failed with error 18: 'Authentication failed.' on server phelbwlabect003.karmalab.net:27017. The full response is { "ok" : 0.0, "errmsg" : "Authentication failed.", "code" : 18, "codeName" : "AuthenticationFailed" }
at com.mongodb.connection.CommandHelper.createCommandFailureException(CommandHelper.java:170)
at com.mongodb.connection.CommandHelper.receiveCommandResult(CommandHelper.java:123)
at com.mongodb.connection.CommandHelper.executeCommand(CommandHelper.java:32)
at com.mongodb.connection.SaslAuthenticator.sendSaslStart(SaslAuthenticator.java:117)
at com.mongodb.connection.SaslAuthenticator.access$000(SaslAuthenticator.java:37)
at com.mongodb.connection.SaslAuthenticator$1.run(SaslAuthenticator.java:50)
... 9 common frames omitted
You are mixing the uri style connection settings with the individual properties style settings.
Either use
spring:
data:
mongodb:
host: localhost
port: 27017
database: SHAM_TEST
username: develop
password: pass
Or
spring:
data:
mongodb:
uri:mongodb://develop:pass#localhost:27017/SHAM_TEST
If your project has more then one application.properties/application.yml file, sometime they both conflicts if one has URI and other has Host/Port/Credential.
This result in the error "Invalid mongo configuration, either uri or host/port/credentials must be specified"
To Avoid the conflict, make sure you either use URI or Host/Port/Credential in all.
The issue was authentication-database was missing.
Here is now the working configuration :
spring:
data:
mongodb:
host: <my_host>
username: develop
password: d3VeL0p$
port: 27017
database: SHAM
repositories:
enabled: true
authentication-database: admin
If you are using application.properties file to store your configuration, Use the following structure.
spring.data.mongodb.host = localhost
spring.data.mongodb.port = 27017
spring.data.mongodb.database = SHAM_TEST
spring.data.mongodb.username = develop
spring.data.mongodb.password = pass
This issue appears with mongo version 4.x,
spring or spring boot supports version 2.x only so when we try to connect with mongo 4 this error appears:
Downgrade your mongo from 4.x to 3.x or lower.
If not, then change these placeholders.
Change from :
spring.data.mongodb.host= localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database= your db name
spring.data.mongodb.username= something
spring.data.mongodb.password= ***
-to-
mongo.replica.hosts=localhost:27017
mongo.dbname= your db name
mongo.username= something
mongo.password= ***
I used NetBeans IDE 8.0.1 "RESTful Web Services from database" wizard to map my table objects with JPA and JAX-RS 2.0.
After the classes were created, with the project options "Test RESTful Web Services", NetBeans itself creates an interface (HTML, css).
This works fine in my localhost. I can connect to my database from the Web Services created, sending GET and POST (JSON) Requests.
Now, I need to access from another domain different from my localhost, so I tried with CORS.
Searching diferent post I used this code:
package CORS;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;
#Provider
#PreMatching
public class CORSResponseFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException {
response.getHeaders().add("Access-Control-Allow-Origin", "*");
response.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
response.getHeaders().add("Access-Control-Allow-Credentials", "true");
response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
}
}
And with this ApplicationConfig class created, the resource (CORSRequestFilter) was added:
package entities.service;
import java.util.Set;
import javax.ws.rs.core.Application;
#javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
addRestResourceClasses(resources);
return resources;
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(CORS.CORSResponseFilter.class);
resources.add(entities.service.AppSettingsFacadeREST.class);
resources.add(entities.service.CategoryFacadeREST.class);
resources.add(entities.service.CityFacadeREST.class);
resources.add(entities.service.EmailInitialSubscriptionFacadeREST.class);
resources.add(entities.service.IdentityProviderFacadeREST.class);
resources.add(entities.service.ItemFacadeREST.class);
resources.add(entities.service.ItemHistoryFacadeREST.class);
resources.add(entities.service.ItemStatusFacadeREST.class);
resources.add(entities.service.PhotoFacadeREST.class);
resources.add(entities.service.UserFacadeREST.class);
resources.add(entities.service.WantedItemsFacadeREST.class);
}
}
And it works perfectly for a while!
I was able to connect to my database to my Glassfish server from another domain using the RESTful web services just fine. I even develop an AngularJS app and could use the RSWebServices too.
Then I started to receive this error:
XMLHttpRequest cannot load http://xx.x.xxx.xx:8080/freeproject/webresources/entities.emailinitialsubscription. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://xxxxxxxxxxx.com' is therefore not allowed access. The response had HTTP status code 400.
The preflight request is returned with a status 200 OK. But the POST request is failed.
Searching on internet I found that Oracle itself https://blogs.oracle.com/theaquarium/entry/supporting_cors_in_jax_rs tells me to follow this post:
http://www.developerscrappad.com/1781/java/java-ee/rest-jax-rs/java-ee-7-jax-rs-2-0-cors-on-rest-how-to-make-rest-apis-accessible-from-a-different-domain/
So, I tried that and I added a new class: resources.add(CORS.CORSRequestFilter.class):
package CORS;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
#Provider
#PreMatching
public class CORSRequestFilter implements ContainerRequestFilter {
#Override
public void filter( ContainerRequestContext requestCtx ) throws IOException {
String path = requestCtx.getUriInfo().getPath();
// IMPORTANT!!! First, Acknowledge any pre-flight test from browsers for this case before validating the headers (CORS stuff)
if ( requestCtx.getRequest().getMethod().equals( "OPTIONS" ) ) {
requestCtx.abortWith( Response.status( Response.Status.OK ).build() );
}
}
}
But it doesn't work. The abortWith function stop the chain of requests and the POST request is never sent.
What can I do here? Any help will be highly appreciated.