Getting server port and contextPath programmatically - springboot - rest

How can i get the server port and contextPath at runtime?
In application.yml, i am setting these values:
server:
port: 9300
contextPath: '/apis'
In the code, i am building a JSONAPI response to include a reference back to the REST API and therefore the need to programmatically get
{
"relationships": {
"company": {
"links": {
"related": "/api/v1/users/1/company"
}
},
"pets": {
"links": {
"related": "/api/v1/users/1/pets"
}
}
}
}
Example,
String related = port? + contextPath? + "/users" + userId + "company";

The following is taken from http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html:
Spring Boot allows you to externalize your configuration so you can
work with the same application code in different environments. You can
use properties files, YAML files, environment variables and
command-line arguments to externalize configuration. Property values
can be injected directly into your beans using the #Value
annotation, accessed via Spring’s Environment abstraction or bound to
structured objects via #ConfigurationProperties.
Spring Boot uses a very particular PropertySource order that is
designed to allow sensible overriding of values. Properties are
considered in the following order:
Devtools global settings properties on your home directory
(~/.spring-boot-devtools.properties when devtools is active).
#TestPropertySource annotations on your tests.
#SpringBootTest#properties annotation attribute on your tests.
Command line arguments.
Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an
environment variable or system property)
ServletConfig init parameters.
ServletContext init parameters.
JNDI attributes from java:comp/env.
Java System properties (System.getProperties()).
OS environment variables.
A RandomValuePropertySource that only has properties in random.*.
Profile-specific application properties outside of your packaged
jar (application-{profile}.properties and YAML variants)
Profile-specific application properties packaged inside your jar
(application-{profile}.properties and YAML variants)
Application properties outside of your packaged jar
(application.properties and YAML variants).
Application properties packaged inside your jar
(application.properties and YAML variants).
#PropertySource annotations on your #Configuration classes.
Default properties (specified using
SpringApplication.setDefaultProperties).
To provide a concrete example, suppose you develop a #Component that
uses a name property:
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*
#Component
public class MyBean {
#Value("${name}")
private String name;
// ...
}
On your application classpath (e.g. inside your jar) you can have an
application.properties that provides a sensible default property value
for name. When running in a new environment, an
application.properties can be provided outside of your jar that
overrides the name; and for one-off testing, you can launch with a
specific command line switch (e.g. java -jar app.jar --name="Spring").
[Tip] The SPRING_APPLICATION_JSON properties can be supplied on the
command line with an environment variable. For example in a UN*X
shell:
$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar
In this example you will end up with foo.bar=spam in the Spring
Environment. You can also supply the JSON as spring.application.json
in a System variable:
$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar
or command line argument:
$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'
or as a JNDI variable java:comp/env/spring.application.json.

Inject Spring Boot properties
You can inject the values in your code this way:
#Value("${server.port}")
private int port;
#Value("${server.contextPath}")
private String contextPath;
Hateoas
Alternatively, you could take a look at the Hateoas project, which can generate the link section for you: http://docs.spring.io/spring-hateoas/docs/current/reference/html

Use #Value annotation to inject the properties into member variables of your class. You can do this:
#Component
public class Foo
{
#Value("${server.port}")
String serverPort;
#Value("${server.contextPath}")
String contextPath;
public void doSomething()
{
String str = "serverPort: " + serverPort + "; contextPath: " + contextPath;
}
}

Related

No API definition provided. - openApi - springdoc

I have a simple boot application where I have added open api swagger dependency
springdoc-openapi-ui
along with these properties
springdoc.swagger-ui.disable-swagger-default-url=true
springdoc.swagger-ui.configUrl=/v3/api-docs/swagger-config
springdoc.swagger-ui.path=/swagger-ui.html
I am getting these error (when calling http://localhost:8080/swagger-ui/index.html):
No API definition provided.
this is my controller :
#RestController
public class HelloWorld {
#GetMapping("sayHi")
public String sayHi(){
return "Hi Beno";
}
}
Any idea ?
When using a different endpoint to serve the OpenAPI Config, you'll need to set two properties
// This will set UI to fetch the config's URL from "somePath"
springdoc.swagger-ui.configUrl=somePath
// You also need to serve the config file from the endpoint at "somePath"
springdoc.api-docs.path=somePath

How to run an Apache Camel integration with Camel K containing: XML file & .java file

Document of Apache Camel K guides how to run an integration wroten by XML. But when I need to write custom code in Java (processors, transform), I can not find the way to run them together. So, have Camel K supported this features? If it have, how can I do that?
You can mix languages like
kamel run --name my-app routes.xml routes.java
Then if your need is to write custom processors in java, then you can bind such processors to the camel registry from your configure method like
getContext().getRegistry().bind("myProcessor", new Processor() { ... }
or by annotating methods with #BindToRegistry in tour RouteBuilder class like
#BindToRegistry("my-processor")
Processor myProcessor() {
return exchange -> { ... }
}

Camel Restlet - Context Path Ambiquity

I have Spring Boot Camel application where rest apis are exposed using camel-restlet
Sample route
#Component
public class AppRoute extends RouteBuilder{
public void configure(CamelContext context){
from("restlet:employee?restletMethods=GET").log("${body}");
}
}
The App runs perfect ( spring-boot:run ). but am unable to locate under which path the API is exposed. Log has no information.
Every API i hit returns 404. Log shows the route has been started. Under which path is it running. And how do I change it?
Note: Please dont suggest any XML based configuration. Anything that I can put under #Configuration would be perfect
I would go with the Rest DSL which is supported by the camel-restlet component like this
restConfiguration().component("restlet").port(8080);
rest("/rest")
.get("employee")
.route().log("${body}")
.endRest();
And this route will listen to the following url
http://localhost:8080/rest/employee
EDIT:
I guess you could do something like without using the Rest DSL
String host = InetAddress.getLocalHost().getHostName();
from("restlet:http://" + host + contextPath + "/employee?restletMethods=GET").log("${body}")
The port and context path are configurable with the following properties
camel.component.restlet.port=8686
server.servlet.context-path=/my-path
The context path can be injected in the routeBuilder with
#Value("${server.servlet.context-path}")
private String contextPath;
According to the documentation, the format of the URI in a restlet endpoint definition should be the following:
restlet:restletUrl[?options]
Where restletUrl should have the following format:
protocol://hostname[:port][/resourcePattern]
So in your case you could define the URI in the following way:
from("restlet:http://localhost/employee?restletMethods=GET")
This should make the endpoint available under the following URL:
http://localhost/employee
Which you can test e.g. in a web browser.
Use the first of the three configuration methods described here:
https://restlet.com/open-source/documentation/javadocs/2.0/jee/ext/org/restlet/ext/servlet/ServerServlet.html
You should be able to customize it using the Component:
https://restlet.com/open-source/documentation/javadocs/2.0/jee/api/org/restlet/Component.html?is-external=true
See in particular setServers() methods (or XML equivalent) to change the hostname and port.

Importing domain classes from GORM-standalone module into Grails

I have 2 pieces of my puzzle:
1) a no-Grails project named core-module with standalone GORM:
dependencies {
compile 'org.grails:grails-datastore-gorm-mongodb:6.0.4.RELEASE'
compile 'org.grails:grails-validation:3.2.3'
}
and domain classes like:
import grails.gorm.annotation.Entity
#Entity
class Module {
String id
String tags
}
the GORM-ing is initialized by
Map config = new Yaml().load this.class.getResource( '/application.yml' ).text
new MongoDatastore( config, Module, UserAccount )
and the domain classes are working as they would in a Grails app.
2) a Grails 3.2.3 app:
dependencies {
// default grails dependencies
compile project( ':core-module' )
compile 'org.grails.plugins:mongodb:6.0.4'
compile 'org.grails.plugins:spring-security-core:3.1.1'
// etc
}
the GORM is initialized so:
def config = config.grails.mongodb
log.info "using $config"
new MongoDatastore( config, Module, UserAccount )
and it prints out this into the log file:
g.app.init.com.mozaiq.Application - using [host:localhost, port:27017, databaseName:theDB, username:theUN, pooled:true, mongoOptions:[connectionsPerHost:100, autoConnectRetry:true, connectTimeout:3000]]
The problem is, that the property grailsApplication.domainClasses is empty, and even though the Module.collection is not-null, the Module.count() return 0 despite the collection being not empty.
Also in my mongo-client I see that upon app start a new database test is created with an empty collection, named by one of my domain classes. If I insert some documents into it, the .count() returns 0 and the CRUD list remains empty.
Grails only scans packages in the application by default for performance reasons. Override limitScanningToApplication() to return false in your Application class and define the packages you wish to scan by overriding packageNames() in your Application class.
Grails will then automatically discover the Mongo GORM classes

Determine web app path

I am using Spring Tool Suite (really eclipse). I just created a new springMVC project and created a simple controller. There was a problem with how STS created the project so I had to manually fix the groupID and artifactID in the pom. The problem I am currently having is I can't seem to hit my tomcat server (published and launched by STS). I have checked the directory structure in tomcat where it gets published and everything seems to be fine but I get 404's when I try and hit the controller. The tomcat logs look as if nothing has even tried to connect to it. They also show that my controller has been mapped:
2013-10-14 09:09:17.763] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/Login],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.verisk.underwriting.ims.web.IMSController.test()
This is what my controller looks like:
#Controller
#RequestMapping("Login")
public class IMSController
{
#RequestMapping(value = "", method = RequestMethod.GET)
#ResponseBody
public String test()
{
return "SUCCESS";
}
}
The app is called ims, so I should be able to hit this controller with this request:
http://localhost/ims/Login
It is configured with a java config (AppConfig.java):
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.some.package.ims.web")
public class AppConfig extends WebMvcConfigurerAdapter
{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
Is there a config file that specifies the base path for the app?
Have a look at the .metadata directory of our workspace. It has a .plugins folder, that constains the org.eclipse.wst.server.core directory, and there is one (or more) tmp0 diectory. That contains a wtpwebapps directory. This contains the deployed webapps with the name that is used -- for example MyApp.
<Workspace>\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\MyApp
Then your Login page is located at
http://localhost[:8080]/MyApp/Login
http://localhost/ims/Login will hit port 80 ; by default tomcat runs on port 8080. So unless you have changed tomcat's HTTP port to 80 you need to use localhost:8080
If the port is good then check that your application context path is really ims, by default it is the exact name of the generated WAR file. If you use WTP, eclipse "servers" view will show it under the server instance.
If the context path is good then check the configured URL mapping in your web.xml descriptor. Make sure you are not missing a prefix in the URL for REST/MVC servlet URL aggregation. In your case it looks like you should use .../resources/Login because your configured your resources to be under the /resources/** pattern.