Change port number in netflix ribbon - spring

I have two services. One runs on port 8001 and it registered in eureka server, other runs on port 8002, and doesn't exist in eureka. I want to change port 8001 to 8002 in my local ribbon client. I have created
public class LocalProxy <T extends DiscoveryEnabledServer> implements ServerListFilter<T>
with method
public List<T> getFilteredListOfServers(List<T> servers)
But I don't know how to change the port. DiscoveryEnabledServer.setPort doesn't work.

Ugly, but it works for me.
private void addProxyRoute(List<T> servers) {
DiscoveryEnabledServer service = findFirst(servers,
s -> "service1".equalsIgnoreCase(s.getInstanceInfo().getAppName()));
if (service == null) return;
IClientConfig clientConfig = new DefaultClientConfigImpl();
DomainExtractingServerList list =
new DomainExtractingServerList(createServer(service.getInstanceInfo()), clientConfig, true);
servers.addAll((Collection<? extends T>) list.getUpdatedListOfServers());
servers.remove(service);
}
private StaticServerList createServer(InstanceInfo app) {
DiscoveryEnabledServer server = new DiscoveryEnabledServer(InstanceInfo.Builder.newBuilder()
.setAppName("service1")
.setPort(8002)
.setHostName(app.getHostName())
.setMetadata(new HashMap<>())
.build(), false, true);
server.setAlive(true);
server.setReadyToServe(true);
return new StaticServerList(server);
}

Related

Connecting to Cassandra Cluster from Springboot application throws "AllNodesFailedException: Could not reach any contact point" Exception

Springboot application is failing to start up because it is failing to connect to the Cassandra contact points. Though the same configuration is working with localhost Cassandra setup but not with the actual Cassandra cluster. Configuration class is given below.
#Configuration
#EnableCassandraRepositories(basePackages = { "xyz.abc" })
public class CassandraConfiguration extends AbstractCassandraConfiguration {
#Value("${cassandra.contactpoints}")
private String contactPoints;
#Value("${cassandra.port}")
private int port;
#Value("${cassandra.keyspace}")
private String keySpace;
#Value("${cassandra.schema-action}")
private String schemaAction;
#Override
protected String getKeyspaceName() {
return keySpace;
}
#Override
protected String getContactPoints() {
return contactPoints;
}
#Override
protected int getPort() {
return port;
}
#Override
public SchemaAction getSchemaAction() {
return SchemaAction.valueOf(schemaAction);
}
The exception message you posted indicates that your application is not able to reach any of the nodes in your cluster.
You haven't provided details of your environment or how you've configured your cluster but the exception mostly relates to networking. You need to make sure that there is network connectivity between your app instances and all the [local] nodes of the Cassandra cluster you're connecting to. Check that there is no firewall blocking access to the CQL client port (default is 9042) on the nodes.
Also check that the Cassandra nodes are configured to listen for client connections on a publicly-reachable interface -- rpc_address in cassandra.yaml should not be set to a private address.
Use Linux utilities such as nc, telnet, netstat and lsof to assist with your troubleshooting. Cheers!

retrofit spring boot not responding

I have a server in spring boot, which is running on port 8080.
Now I'm trying to call rest api in my android application using retrofit2.
Here is what I have implemented:
final TextView textView=findViewById(R.id.t1);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:8080/")
.addConverterFactory(GsonConverterFactory.create())
.build();
JsonPlaceHolderApi jsonPlaceHolderApi = retrofit.create(JsonPlaceHolderApi.class);
Call<TC> call = jsonPlaceHolderApi.getPosts();
call.enqueue(new Callback<TC>() {
#Override
public void onResponse(Call<TC> call, Response<TC> response) {
textView.setText(response.toString());
if (!response.isSuccessful()) {
return;
}
TC posts = response.body();
textView.setText(posts.toString());
}
#Override
public void onFailure(Call<TC> call, Throwable t) {
}
});
I can surly say that, it's not working as my api is not even being called. As the hello world screen remains as it is.
And in my server I have logger, which doesn't log anything, so it doesn't get called.
Here is my CORS:
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("*")
.allowedOrigins("*");
}
};
}
The problem is with the word localhost.
As for debugging purpose I'm connecting the android device with my PC so my android device can't connect to localhost as it is just an alias of my IP address.
To resolve this, I opened up CMD and wrote ipconfig, by this command I can see all details related to IP.
And here it shows my IPv4 address as $.$.$.$. I just replaced the localhost with that $.$.$.$.
Now everything is working fine.
Any ideas how to make it work with Asp.net core. I just test it wih my local machine ip address and work perfectly.
Unfortunately, not the case with Asp.net core.
aAndroid + Retrofit + Asp.net API "java.security.cert.CertPathValidatorException: Trust anchor for certification path not found."

Can my Spring Boot application run HTTPS only on certain #RequestMappings?

I'm working on a Spring application that is for a smart house. I got the micro-controllers that send data to the Spring application, but I can not implement SSL on them on account of not enough space and processing speed.
On the client-side, I want to use HTTPS, because the client runs on Android.
Can I map certain requests to HTTP and others to HTTPS?
Can we not open two ports from the spring boot application one on 443 other on 80. So that, on https it listens to 443 and on http to 80. So in your app you can configure http on a url to use 80 port and https to use 443 port.
We can do this by, changes in application.properties:
#Https settings
server.port=443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password = secret
server.ssl.key-password = secret
#Http setting
server.http.port=80
I am giving an example using Undertow server, you can do this on any application server (tomcat, etc):
#SpringBootApplication
public class Boot {
#Value("${server.http.port:0}")
private Integer httpPort;
public static void main(String[] args) throws Exception {
SpringApplication.run(Boot.class, args);
}
#Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
public void customize(Builder builder) {
// worker options
builder.setWorkerThreads(500);
builder.setWorkerOption(Options.TCP_NODELAY, true);
// io options
builder.setIoThreads(Runtime.getRuntime().availableProcessors() * 2);
// socket options
builder.setSocketOption(Options.BACKLOG, 10000);
builder.setSocketOption(Options.TCP_NODELAY, true);
builder.setSocketOption(Options.REUSE_ADDRESSES, true);
// server options
builder.setServerOption(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, false);
builder.setServerOption(UndertowOptions.ALWAYS_SET_DATE, true);
builder.setServerOption(UndertowOptions.RECORD_REQUEST_START_TIME, false);
// Done to keep both http and https port open at production
if (httpPort > 0)
builder.addHttpListener(httpPort, "0.0.0.0");
}
});
return factory;
}
}

How can I make WireMock port more dynamic to use it for testing service

I am using wiremock to mock github api to do some testing of my service.
The service calls github api. For the tests I am setting endpoint property to
github.api.endpoint=http://localhost:8087
This host and port are the same as wiremock server #AutoConfigureWireMock(port = 8087) so I can test different scenarios like : malformed response, timeouts etc.
How can I make this port dynamic to avoid case when it is already used by system ? Is there a way to get wiremock port in tests and reassign endpoint property ?
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureWireMock(port = 8087)
#TestPropertySource(properties ={"github.api.endpoint=http://localhost:8087"})
public class GithubRepositoryServiceTestWithWireMockServer {
#Value("${github.api.client.timeout.milis}")
private int githubClientTimeout;
#Autowired
private GithubRepositoryService service;
#Test
public void getRepositoryDetails() {
GithubRepositoryDetails expected = new GithubRepositoryDetails("niemar/xf-test", null,
"https://github.com/niemar/xf-test.git", 1, "2016-06-12T18:46:24Z");
stubFor(get(urlEqualTo("/repos/niemar/xf-test"))
.willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("/okResponse.json")));
GithubRepositoryDetails repositoryDetails = service.getRepositoryDetails("niemar", "xf-test");
Assert.assertEquals(expected, repositoryDetails);
}
#Test
public void testTimeout() {
GithubRepositoryDetails expected = new GithubRepositoryDetails("niemar/xf-test", null,
"https://github.com/niemar/xf-test.git", 1, "2016-06-12T18:46:24Z");
stubFor(get(urlEqualTo("/repos/niemar/xf-test"))
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withBodyFile("/okResponse.json")
.withFixedDelay(githubClientTimeout * 3)));
boolean wasExceptionThrown = false;
try {
GithubRepositoryDetails repositoryDetails = service.getRepositoryDetails("niemar", "xf-test");
} catch (GithubRepositoryNotFound e) {
wasExceptionThrown = true;
}
Assert.assertTrue(wasExceptionThrown);
}
You have to set the WireMock port to 0 so that it chooses a random port and then use a reference to this port (wiremock.server.port) as part of the endpoint property.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureWireMock(port = 0)
#TestPropertySource(properties = {
"github.api.endpoint=http://localhost:${wiremock.server.port}"
})
public class GithubRepositoryServiceTestWithWireMockServer {
....
}
See also Spring Cloud Contract WireMock.
I know this is a bit old post but still there is a documented way to have these ports dynamically. Read more here: Getting started. Just scroll down a bit to 'Random port numbers'.
From the documentation there:
What you need to do is to define a Rule like so
#Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort());
And then access them via
int port = wireMockRule.port();
int httpsPort = wireMockRule.httpsPort();
One more way, you can use dynamic port without conflict is
import org.springframework.util.SocketUtils;
int WIREMOCK_PORT = SocketUtils.findAvailableTcpPort();
public WireMockRule wireMockServer = new WireMockRule(WIREMOCK_PORT);
if you want to access it from properties file, then we have wiremock.server.portprovided by Wiremock
"github.api.endpoint=http://localhost:${wiremock.server.port}"
I am not aware of #AutoConfigureWireMock but if you are manually starting wiremock and setting up mocks, while starting spring you can setup a random port number utilizing spring random. A sample will look like this
in your wiremock class
#Component
public class wiremock {
#Value("${randomportnumber}")
private int wiremockPort;
public void startWiremockServer() {
WireMock.configureFor("localhost", wiremockPort);
wireMockServer = new com.github.tomakehurst.wiremock.WireMockServer(wireMockConfig().port(wiremockPort).extensions
(MockedResponseHandler.class));
wireMockServer.start();
}
}
In your test class
//however you want to configure spring
public class wiremock {
#Value("${github.api.endpoint}")
private String wiremockHostUrl;
//use the above url to get stubbed responses.
}
in your application.properties file
randomportnumber=${random.int[1,9999]}
github.api.endpoint=http://localhost:${randomportnumber}

Not using port in the url

I use spring boot (tomcat embedded) and ssl.
Actually, I need to type the port (8443) in the url to be able to access web applicaiton.
How to be able to use domnain name only?
Something like
https://www.bob.com
instead of
https://www.bob.com:8443/
Edit
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat
= new TomcatEmbeddedServletContainerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(createHttpConnector());
return tomcat;
}
private Connector createHttpConnector() {
Connector connector
= new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setSecure(false);
connector.setPort(8080);
connector.setRedirectPort(8443);
return connector;
}
now not need to type port
but if it type bob.com, browser convert to
bob.com:8443
Default port used by browsers for HTTP is 80 and HTTPS is 443. If you run your application on 443 (since you are using HTTPS), you don't have to use the port number, browser will automatically reroute your URL. To change the port number in you spring-boot applicatioN specify server.port property in bootstrap.yml.
server:
port: 443
Do you mean something like this?
String webPort = System.getenv("PORT");
if(webPort == null || webPort.isEmpty()) {
webPort = "8080";
}

Resources