Port binding for Spring RESTful Web Service - spring

I've used the Building a RESTful Web Service tutorial to build a WebService for my purpose. It was quite easy, but now I'm struggeling to configure the port the WebService should be binded through. There is no config.xml or anything to configure in this project. Can anyone give me a hint about how to configure the WebService's port?
As these details might be helpful. I'm starting the server with the code below, containing the #EnableAutoConfiguration tag. The configuration is done by Spring Boot.
#ComponentScan
#EnableAutoConfiguration
public class ServerStarter{
public static void main(String[] args) {
SpringApplication.run(ServerStarter.class, args);
}
}

To configure the ports you can set the server.port and management.port properties by writing the following in the "application.properties" file located under "src/main/resources":
server.port = 9000
management.port = 9001
Similarly if you need to specify the management address:
management.address = 127.0.0.1
There are more properties you can set for the server and management server. See spring-boot's documentation: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/

For a quick and dirty solution you can employ the command line option arguments (source):
--server.port=9000

Related

How to register spring boot microservices on spring cloud Netflix eureka?

We were planning to use spring cloud Netflix oss components. So I was doing a small sample project.
I developed 2 spring microservices and those services runs well on
http://localhost:9000/microsvc-one http://localhost:9001/microsvc-two
And also wrote a sample spring cloud etflix eureka maven project which runs well on
http://localhost:8761
I used annotations #EurekaDiscoveryClient and #SpringBootApplication on both the spring boot microservices main class
I used annotation #EnableEurekaServer and #SpringBootApplication
Now I am facing a problem in registering those services in eureka server. I referred some samples. I am not understanding those.
I did some changes in application.yml files of microsvc-one and microsvc-two and also application.yml file of eureka server.
But still it shows empty.
What all changes are required or missing or correct configuration to be done so that my services are being registered on eureka.
I also have other question like do i need to create a separate project which has #EnableConfigServer and #SpringBootApplication Annotations other than the above 2 microservices and eureka server project module to register the services on eureka.
I see those in most of the examples.
If yes..how do we link between all these?
If you are using springBoot application you will need the annotaion #SpringBootApplication thats why that annotation is there on the project you are seeing. #EnableConfigServer is when you are using the spring-cloud config server it is used to externalize the configuration properties but since you have the application.yml inside the project so you donot need that either.
I am thinking you have a spring boot application for both Microservices and the Eureka server. You need to annotate the eureka main class with
#SpringBootApplication
#EnableEurekaServer
#EnableDiscoveryClient
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
Additionally you need annotate you microservice's main class with..
#SpringBootApplication
#EnableDiscoveryClient
public class MicroApplication {
public static void main(String[] args) {
SpringApplication.run(MicroApplication.class, args);
}
}
Since you donot have you application.yml file in the question here is what you need.
You need the below configuration in application.yml of the microservices.
eureka:
client:
serviceUrl:
defaultZone: ${eurekaurl:http://localhost:8761/eureka/}
In the Eureka Server application.yml file I have this in mine. you might need to tweak it based on what you want.
info:
component: Registry Server
server:
port: ${port:8761}
eureka:
client:
registerWithEureka: false
fetchRegistry: false
server:
enable-self-preservation: false
waitTimeInMsWhenSyncEmpty: 0
instance:
hostname: localhost
lease-expiration-duration-in-seconds: 15
lease-renewal-interval-in-seconds: 5
Suppose you have a microservice named "LoginServer" now, let's see how to register this service with discovery server (Eureka Server) at startup.
Here Spring Boot startup class of LoginServer.java:
#EnableAutoConfiguration
#EnableDiscoveryClient
public class LoginServer {
public static void main(String[] args) {
// Will configure using login-server.yml
System.setProperty("spring.config.name", "login-server");
SpringApplication.run(LoginServer.class, args);
}
}
The #EnableDiscoveryClient - enables service registration and discovery. In this case, this process registers itself with the discovery-server service using its application name, that is configured in YML configuration file.
let's see the complete setup:
First create a login-server.yml (any name but extension should be .yml) file into src/main/resources package folder. And write those configurations and save.
# Spring properties
spring:
application:
name: login-server # This name used as ID so ("spring.config.name",
#"login-server"); must be same.
# Discovery Server Access
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
# HTTP Server
server:
port: 2222 # HTTP (Tomcat) port
Run the LoginServer and let it finish initializing. Open the dashboard by putting this URL http://localhost:1111 in your favorite browser and refresh. After few seconds later you should see the LOGIN-SERVER. Generally registration takes up to 30 seconds (by default) so wait or restart.
And this is the microservice complete registration process.

Spring boot Artemis embedded broker behaviour

Morning all,
I've been struggling lately with the spring-boot-artemis-starter.
My understanding of its spring-boot support was the following:
set spring.artemis.mode=embedded and, like tomcat, spring-boot will instanciate a broker reachable through tcp (server mode). The following command should be successful: nc -zv localhost 61616
set spring.artmis.mode=native and spring-boot will only configure the jms template according to the spring.artemis.* properties (client mode).
The client mode works just fine with a standalone artemis server on my machine.
Unfortunatelly, I could never manage to reach the tcp port in server mode.
I would be grateful if somebody confirms my understanding of the embedded mode.
Thank you for tour help
After some digging I noted that the implementation provided out of the box by the spring-boot-starter-artemis uses org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory acceptor. I'm wondering if that's not the root cause (again I'm by no means an expert).
But it appears that there is a way to customize artemis configuration.
Therefore I tried the following configuration without any luck:
#SpringBootApplication
public class MyBroker {
public static void main(String[] args) throws Exception {
SpringApplication.run(MyBroker.class, args);
}
#Autowired
private ArtemisProperties artemisProperties;
#Bean
public ArtemisConfigurationCustomizer artemisConfigurationCustomizer() {
return configuration -> {
try {
configuration.addAcceptorConfiguration("netty", "tcp://localhost:" + artemisProperties.getPort());
} catch (Exception e) {
throw new RuntimeException("Failed to add netty transport acceptor to artemis instance");
}
};
}
}
You just have to add a Connector and an Acceptor to your Artemis Configuration. With Spring Boot Artemis starter Spring creates a Configuration bean which will be used for EmbeddedJMS configuration. You can see this in ArtemisEmbeddedConfigurationFactory class where an InVMAcceptorFactory will be set for the configuration. You can edit this bean and change Artemis behaviour through custom ArtemisConfigurationCustomizer bean which will be sucked up by Spring autoconfig and be applied to the Configuration.
An example config class for your Spring Boot application:
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory;
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisConfigurationCustomizer;
import org.springframework.context.annotation.Configuration;
#Configuration
public class ArtemisConfig implements ArtemisConfigurationCustomizer {
#Override
public void customize(org.apache.activemq.artemis.core.config.Configuration configuration) {
configuration.addConnectorConfiguration("nettyConnector", new TransportConfiguration(NettyConnectorFactory.class.getName()));
configuration.addAcceptorConfiguration(new TransportConfiguration(NettyAcceptorFactory.class.getName()));
}
}
My coworker and I had the exact same problem as the documentation on this link (chapter Artemis Support) says nothing about adding an individual ArtemisConfigurationCustomizer - Which is sad because we realized that without this Customizer our Spring Boot App would start and act as if everything was okay but actually it wouldn't do anything.
We also realized that without the Customizer the application.properties file is not beeing loaded so no matter what host or port you mentioned there it would not count.
After adding the Customizer as stated by the two examples it worked without a problem.
Here some results that we figured out:
It only loaded the application.properties after configuring an ArtemisConfigurationCustomizer
You don't need the broker.xml anymore with an embedded spring boot artemis client
Many examples showing the use of Artemis use a "in-vm" protocol while we just wanted to use the netty tcp protocol so we needed to add it into the configuration
For me the most important parameter was pub-sub-domain as I was using topics and not queues. If you are using topics this parameter needs to be set to true or the JMSListener won't read the messages.
See this page: stackoverflow jmslistener-usage-for-publish-subscribe-topic
When using a #JmsListener it uses a DefaultMessageListenerContainer
which extends JmsDestinationAccessor which by default has the
pubSubDomain set to false. When this property is false it is
operating on a queue. If you want to use topics you have to set this
properties value to true.
In Application.properties:
spring.jms.pub-sub-domain=true
If anyone is interested in the full example I have uploaded it to my github:
https://github.com/CorDharel/SpringBootArtemisServerExample
The embedded mode starts the broker as part of your application. There is no network protocol available with such setup, only InVM calls are allowed. The auto-configuration exposes the necessary pieces you can tune though I am not sure you can actually have a TCP/IP channel with the embedded mode.

Spring boot JDBC with password lease/renew (as in Vault)

Hashicorp's Vault can be set up to provide database passwords on demand; each password can be used for a certain "lease" period (say 1 hour) before being renewed, and a maximum use period can be set after which the password has to be trashed and a new one obtained.
In Spring Boot, the JDBC connection is configured at application start, and it is assumed that the JDBC password is coded in the application.properties file (or, alternatively, obtained at application bootstrap time via Spring Cloud Config or equivalent) and used forever.
QUESTION: How might I implement a way in Spring Boot to reset the JDBC password by accessing Vault when a connection attempt fails due to an expired password?
Is there a way to set some sort of handler gets invoked when the connection fails due to an old password, and resets it to a new value?
Check out this open source project available on GitHub; I think it might just be what you are looking for. Note: From the looks of it, this is currently a Spring Cloud Incubator project (has the potential of becoming an official Spring endorsed open source library in the future), and there are only three contributors. You would have to see if it is "reliable enough" to suit your needs.
https://github.com/spring-cloud-incubator/spring-cloud-vault-config
--- Here's a quick summary of useful information ---
Add the following dependency to pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-vault-starter-config</artifactId>
<version>x.y.z</version>
</dependency>
Create a standard Spring Boot application - provided example is just a main application class:
#SpringBootApplication
#RestController
public class Application {
#RequestMapping("/")
public String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
When it runs it will pick up the external configuration from the
default local Vault server on port 8200 if it is running. To modify
the startup behavior you can change the location of the Vault server
using bootstrap.properties (like application.properties but for the
bootstrap phase of an application context), e.g.
bootstrap.yml:
spring.cloud.vault:
host: localhost
port: 8200
scheme: http
connection-timeout: 5000
read-timeout: 15000
host sets the hostname of the Vault host. The host name will be used for SSL certificate validation
port sets the Vault port
scheme setting the scheme to http will use plain HTTP. Supported schemes are http and https.
connection-timeout sets the connection timeout in milliseconds
read-timeout sets the read timeout in milliseconds

Spring Boot: Change Port for Web Application

I am currently trying to create a web application with Spring Boot. I need to host my application to localhost:8081. How do I change the port?
Actually you want to change server.port and you can change it in many different ways as described http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config
Examples:
in your application.properties (in or outside the jar)
command line
java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
and much more
By default spring boot uses port 8080, BUT you can change the port just by adding the following code line in your main() like this:
System.getProperties().put( "server.port", *YOUR_PORT_NUMBER_GOES_HERE* );
e.g
#SpringBootApplication
public class MyClass {
public static void main(String[] args) {
System.getProperties().put( "server.port", 8181 ); //8181 port is set here
SpringApplication.run(MyClass.class, args);
}
OR
You can configure it in your application.properties file like so:
server.port=8181
If you DON'T have an application.properties file in your spring-boot application, you can go ahead and create one. Right-click on the src/java/resources folder and go to New-> Other-> General and choose 'File' then name as: application.properties
Any other configurations you might need are listed here https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html. These properties are also configured in the application.properties file.
Actually you want to change server.port and you can change it in many different ways as described
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config
Put server.port=9000 in your application.properties
In your application.properties file, just add one line
server.port = 8080
And for more configurations you can refer Spring Boot documentation on port
If you are using the embedded tomcat server, you can configure the EmbeddedServletContainerFactory bean yourself in your Application class annotated with #SpringBootApplication.
This will give you options to customize your tomcat server, example configuration
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setPort(9000);
factory.setSessionTimeout(10, TimeUnit.MINUTES);
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
return factory;
}
You could also do the same for Jetty, using the JettyEmbeddedServletContainerFactory bean, or for Undertow using the UndertowEmbeddedServletContainerFactory .
Official documentation found here : http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/
If you're using STS, you can do it following below steps:
Go to Boot Dashboard view, you'll see your Boot app, say myApp1
Right click and click on Open Config. This should open Run Time
Configuration section.
Go to Argument tab and add parameter server.port=, like in the example below, a custom port 9091 is added.
Start the app and if everything is good, you'll see the desired port
on Boot dashboard.
go to your application.properties file and type server.port=8081
see this image

How can I specify my .keystore file with Spring Boot and Tomcat?

I'm trying to set up Spring Security to work with Spring Boot's embedded Tomcat instance. There are quite a few basic samples that do this but I'm stuck where they leave off -- they do basic authentication over HTTP (not HTTPS).
I could probably make it work if I had access to the Tomcat configuration files (server.xml) but since Spring Boot uses an embedded Tomcat instance (which is otherwise a huge convenience), I dont have access to the Tomcat configuration files (at least, not to my knowledge).
There may be an application.properties setting for this but I haven't been able to track it down. I've seen references to a server.contextPath field in application.properties that I suspect may have something to do with replacement Tomcat config files. Even if it is related, I wouldn't know where to begin anyway -- all of the Tomcat SSL instructions I've seen start with editing an existing server.xml file, not building one from scratch.
Can this be done with Spring Boot (either by somehow specifying a snippet of server.xml or through other means)? If not, what would be the simplest way to do this? I understand that I may need to exclude the Tomcat component of Spring Boot but I'd prefer to avoid that if possible.
Starting with Spring Boot 1.2, you can configure SSL using application.properties or application.yml. Here's an example for application.properties:
server.port = 8443
server.ssl.key-store = classpath:keystore.jks
server.ssl.key-store-password = secret
server.ssl.key-password = another-secret
Same thing with application.yml:
server:
port: 8443
ssl:
key-store: classpath:keystore.jks
key-store-password: secret
key-password: another-secret
Here's a link to the current reference documentation.
For external keystores, prefix with "file:"
server.ssl.key-store=file:config/keystore
It turns out that there is a way to do this, although I'm not sure I've found the 'proper' way since this required hours of reading source code from multiple projects. In other words, this might be a lot of dumb work (but it works).
First, there is no way to get at the server.xml in the embedded Tomcat, either to augment it or replace it. This must be done programmatically.
Second, the 'require_https' setting doesn't help since you can't set cert info that way. It does set up forwarding from http to https, but it doesn't give you a way to make https work so the forwarding isnt helpful. However, use it with the stuff below, which does make https work.
To begin, you need to provide an EmbeddedServletContainerFactory as explained in the Embedded Servlet Container Support docs. The docs are for Java but the Groovy would look pretty much the same. Note that I haven't been able to get it to recognize the #Value annotation used in their example but its not needed. For groovy, simply put this in a new .groovy file and include that file on the command line when you launch spring boot.
Now, the instructions say that you can customize the TomcatEmbeddedServletContainerFactory class that you created in that code so that you can alter web.xml behavior, and this is true, but for our purposes its important to know that you can also use it to tailor server.xml behavior. Indeed, reading the source for the class and comparing it with the Embedded Tomcat docs, you see that this is the only place to do that. The interesting function is TomcatEmbeddedServletContainerFactory.addConnectorCustomizers(), which may not look like much from the Javadocs but actually gives you the Embedded Tomcat object to customize yourself. Simply pass your own implementation of TomcatConnectorCustomizer and set the things you want on the given Connector in the void customize(Connector con) function. Now, there are about a billion things you can do with the Connector and I couldn't find useful docs for it but the createConnector() function in this this guys personal Spring-embedded-Tomcat project is a very practical guide. My implementation ended up looking like this:
package com.deepdownstudios.server
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory
import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.boot.*
import org.springframework.stereotype.*
#Configuration
class MyConfiguration {
#Bean
public EmbeddedServletContainerFactory servletContainer() {
final int port = 8443;
final String keystoreFile = "/path/to/keystore"
final String keystorePass = "keystore-password"
final String keystoreType = "pkcs12"
final String keystoreProvider = "SunJSSE"
final String keystoreAlias = "tomcat"
TomcatEmbeddedServletContainerFactory factory =
new TomcatEmbeddedServletContainerFactory(this.port);
factory.addConnectorCustomizers( new TomcatConnectorCustomizer() {
void customize(Connector con) {
Http11NioProtocol proto = (Http11NioProtocol) con.getProtocolHandler();
proto.setSSLEnabled(true);
con.setScheme("https");
con.setSecure(true);
proto.setKeystoreFile(keystoreFile);
proto.setKeystorePass(keystorePass);
proto.setKeystoreType(keystoreType);
proto.setProperty("keystoreProvider", keystoreProvider);
proto.setKeyAlias(keystoreAlias);
}
});
return factory;
}
}
The Autowiring will pick up this implementation an run with it. Once I fixed my busted keystore file (make sure you call keytool with -storetype pkcs12, not -storepass pkcs12 as reported elsewhere), this worked. Also, it would be far better to provide the parameters (port, password, etc) as configuration settings for testing and such... I'm sure its possible if you can get the #Value annotation to work with Groovy.
If you don't want to implement your connector customizer, you can build and import the library (https://github.com/ycavatars/spring-boot-https-kit) which provides predefined connector customizer. According to the README, you only have to create your keystore, configure connector.https.*, import the library and add #ComponentScan("org.ycavatars.sboot.kit"). Then you'll have HTTPS connection.
And here's an example of the customizer implemented in Groovy:
https://github.com/UniconLabs/orville/blob/master/web/src/main/groovy/org/apereo/openregistry/config/TomcatSslConfiguration.groovy

Resources