I've been looking for a way to change the url my microservice is depending on from one environment to another, they told me that I should use spring cloud, and there is currently an application.yml that is used for deployment in openshift, but my knowledge of Spring Cloud is limited and I don't know how to inject the value of the application.yml URL into my java program.
String uri = "http://127.0.0.1:8080/route";
I am looking to change this variable depending on whether it is local, or in development
Why? For communication between microservices
private RestTemplate call = new RestTemplate();
Arrays.asList(call.getForObject(uri, Object[].class));
In local need: "http://127.0.0.1:8080/route";
In dev need : "http://www.myurl.com/route"
I hope I explained myself well
Thanks.
Ok, i think have the solution for my problem.
As I am using Openshift for deployments, and the local configuration for something else, I have used Spring Cloud with a configuration server, making it use one configuration locally, and in development another one overwriting the local configuration.
This solved my problem, thanks to other guys to answer with any solutions.
As "M. Deinum" and "Ken de Guzman" have already mentioned, use the "Spring Profiles" approach.
See here the docs, which explain the functionality:
External configuration: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
Usage of Profiles: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-profiles or https://springframework.guru/spring-profiles/
In-depth read: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-environment
Related
I am currently creating a Java Spring application that works with the spring security JWT. Everywhere I look and read about the "secret string", it says should be changed in production. Like this line in my application.properties: security.jwt.secret="this-is-a-512-bit-key-used-for-signing-jwt-tokens-that-should-be-changed-production"
As well as in stackoverflow question that are sort-of related like this one here: How to include jwt secret in application.yaml for Java Spring.
My question is, what should that string become in production? Am I supposed to generate this somewhere in a SecurityConfig class? Or should I generate a 512 bit string and just paste that in the application.properties file?
Thanks in advance.
Secrets should not be added in your regular application.properties file because that would be checked into your version control system. There are various ways to externalize configuration but the easiest is usually to define environment variables.
In your case, you would need an environment variable called SECURITY_JWT_SECRET and Spring Boot will pick this up automatically.
One way to change properties of a spring app is using Spring Cloud Config. Basically your config is in a GitHub repo and as soon as you modify, Spring cloud config server propagates it to other applications referencing it through application.properties.
https://cloud.spring.io/spring-cloud-config/reference/html/
I will share how it has been done in our application which I think one of the standard way of storing credentials.
There may be alternate ways also.
Its not ideal to store token or credentials in properties
We can externalize the token into Vault or config server
when server starts spring application can fetch the properties
Access to vault are controlled
As we have different vault servers across environments, we can store and change the token in runtime and refresh the application.
Regarding generating the jwt token, it should have some expiry time and refreshed periodically.
Am trying spring cloud config server and client as stand-alone separate applications.
on git, i have folder structure like below-
my-config
----projectfolder1
--------application.properties
----projectfolder2
--------application.properties
I would like that spring cloud client named "projectfolder1" should search application.properties within projectfolder1 on git from spring cloud server i.e
----projectfolder1
--------application.properties
and client "projectfolder2" should get the below mentioned properties from spring cloud config server
----projectfolder2
--------application.properties
My Spring Cloud Config server application.properties has-
spring.cloud.config.server.git.search-paths='{application}'
projectfolder1 in its bootstrap.properties has
spring.application.name=projectfolder1
and projectfolder2 in its bootstrap.properties has
spring.application.name=projectfolder2
According to spring cloud config documentation '{application}' in search path should find the files within the "resolved application name" folder on git. But the above '{application}' doesn't work for me. Clients projectfolder1 and projectfolder2 are not able to get any property at all.
pls assist. i know its possible duplicate of another question on stack overflow. but that question is not resolved and i do not have rights to comment on any question being a new user, So i created this as another question here.
I solved it myself.
The trick is to give search-path {application} without quotes as given below.
It was a little tricky as spring documentation mentions it as '{application}' , probably spring developers just wanted to highlight it with quotes.
spring.cloud.config.server.git.search-paths={application}
instead of
spring.cloud.config.server.git.search-paths='{application}'
My target is to build a GraphQL server on Spring with (1) GraphiQL IDE (2) dynamic GraphQL schema at run-time. My GraphQL engine is GraphQL-Java.
In my first try, I use graphql-java-spring-boot-starter-webmvc and graphiql-spring-boot-starter.
Both the GraphQL server and the GraphiQL work well.
However, under the graphql-java-spring-boot-starter-webmvc framework, a #Bean of GraphQL class is needed. In this bean, the schema is loaded when the server starts so it could not been updated.
In my second try, I don't use graphql-java-spring-boot-starter-webmvc. Instead, I choose spring-boot-starter-web to start the web server and define my own RestController. This is easy to update the GraphQL instance. But I don't find a way to integrate with GraphiQL. I googled GraphiQL+Spring but all solutions are with graphql-java-spring-boot-starter.
Appreciate if anyone could provide me an idea on either approach.
It can be enabled in properties:
graphql.graphiql.enabled=true
It is accessible via the root url +/graphiql example http://localhost:8080/graphiql
You can find a good detailed example here : https://github.com/NoorKrichen/GraphQL-Spring-Boot-Example
Do you have a sample of your setup in git?
It sounds like some configuration problem. But naturally using graphql-java-spring-boot-starter-webmvc all your *.graphql schemas should be picked up in the configured schema resource path. check if you have the path set in your application.yml or if your schema is in the configured path if its already set or by default.
On your second point: "I googled GraphiQL+Spring but all solutions are with graphql-java-spring-boot-starter."
This makes sense for quick guides and demos as using Springboot the plumbing is somehow hidden away from you so that you can focus on the technology at hand being demo'd in this case GraphQl.
On GraphiQL:
Sounds like you are intending to have this embedded with your application, you may not want to do so in production. Depending on your use case there are many other alternatives that are standalone and gives you all the functionality of GraphiQL plus more e.g Altair Graphql Client and Insomnia to name a few.
I'm writing my first "real" applicaion in my first job. I could deploy my app using Spring Boot and it works just fine. One thing that i doubt is datasource config part. Now i write all datasource config in application.properties file:
spring.datasource.url = jdbc:postgresql://10.60.6.34:5432/postgres
spring.datasource.username = *username*
spring.datasource.password = *password*
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQL94Dialect
And that's it! What else should i do to make my app production ready? What about connection pooling and all that stuff? (i'm not quite familiar with all that datasource config stuff) Thanks in advance!
So Joe W is not wrong - profiles is an OK way to handle this issue. However, what I'd recommend instead is to handle the issue using environment variables. This will make your application compatible across not only all operating systems (which profiles will too), but will also allow you to run it within Docker (containers) more easily. You will need to do some amount of this anyway, since profiles still requires you to specify which profile you're running, which you'll need to do with an environment variable.
Luckily for you, Spring Boot auto-wires environment variables with no extra work on your side. You can read more about this here: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
When dealing with environment variables, you use underscores instead of periods, so your configs would look like this:
SPRING_DATASOURCE_URL = jdbc:postgresql://10.60.6.34:5432/postgres
SPRING_DATASOURCE_USERNAME = *username*
SPRING_DATASOURCE_PASSWORD = *password*
SPRING_JPA_HIBERNATE_DDL_AUTO = update
SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT = org.hibernate.dialect.PostgreSQL94Dialect
Then you can set your environment variables to whatever you want, and you don't need to worry about pulling in new profiles for each server. In addition, since environment variables are higher in the hierarchy than file-based configurations, you can leave your current file-based configurations alone (if you'd like) and your environment variables will override them when you deploy.
Around your connection pooling, this is going to heavily depend on your backing servlet container (I.e., tomcat vs other) and your backing database (looks like postgres). I'd recommend you look at tomcat-jdbc usage with Spring boot, which will then allow you to configure the things like max connection pools and such within Spring's environment variables as well.
You should take advantage of SpringBoot profiles that will allow you to define separate configuration for dev, stage, prod, and any other environment you want based on a property.
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
A profile gives you a way to control which configuration is loaded based on a property that defines where the application is deployed.
Your question on data connection pooling depends on your backing data storage selection and how that particular storage is setup. In general, when you go to production you should be using connection pooling of some kind but how much and what kind depend on your implementation.
Additionally, you can use spring config service . Config-service is central location(which can be more secure) for all properties and with very minimal configuration/change your spring-boot application can read properties from config-service.
You should provide your database parameters as environment variables then set them in your application.properties as placeholders. For example:
spring.datasource.url=${DATASOURCE_URL}
Where DATASOURCE_URL is one of the env. variable.
In your IDE you set them in the project setting (for example)
So at your work you set your local parameters in IDE, and on the production machine you set prod parameters as environment variable.
In a J2EE application, how do I create a global Filter that can access other webapps installed on that app server?
In case anyone is still interested, here are my findings regarding this question:
For tomcat and others webapp servers derived from it (eg: JBoss), you can add your filter to the "global" web.xml, usually located under $TOMCAT_HOME/conf/web.xml.
For Websphere, I´ve found the following article to be useful: http://www-03.ibm.com/support/techdocs/atsmastr.nsf/WebIndex/WP101859 . In this case, the basic idea is that you write a ServletContext Listener and uses it to attach your filter to the app
The Servlet-API does not provide such a security leak. But some containers offer alike. Have a look at the <Valve> Configuration of Apache Tomcat. Maybe there is a similar functionality for webshere, but typically you need to hire a ibm consultant to "find" the configuration.
Some application servers/servlet containers (Tomcat, JBoss) provide the cross context feature. It does depend on what you're running your application within however, it's not a J2EE feature.
http://tomcat.apache.org/tomcat-5.5-doc/config/context.html
I'm not sure whether this will help you in what you want to do. What is it exactly? : )
Take a look at this response as well:
What does the crossContext attribute do in Tomcat? Does it enable session sharing?
There is no way to do this in a container/platform independent way. Your J2EE container might provide hooks for you to do this though.
This worked for me: https://stackoverflow.com/a/8815211/964681
Sorry, couldn't just comment on your question. Haven't enough "points".