I have a common class in which I am having a static map as :
private static Map<String,List<Logging>> loggingResponseMap ;
public static Map<String, List<Logging>> getLoggingResponseMap() {
return Logging.loggingResponseMap;
}
public static void setLoggingResponseMap(Map<String, List<Logging>> loggingResponseMapObj) {
Logging.loggingResponseMap = loggingResponseMapObj;
}
I am setting the value in this map in one micrservice and trying to access it in other microservice but instead of getting the data I am getting null in other other microservice.
What could be the reason ?? Is it possible to access the static map across microservice ?
Thanks
No, you will not be able to access any variables, not just static variables, of one microservice in an another microservice. This is not specific to spring-boot, it is the same for any java program. You will have to load the data to the variable separately in each service.
If you are looking to avoid repeated code to the load data in each microservice, you can move the code to a common program and add the common program as as dependency in all the microservices where you want to load the data.
Related
I am developing a web-application using java and spring-boot on AWS Lambda Service.
I am designing it to have one database-service. This will be collections of Entity(table) and JPARepositories classes. So If I need to have any database schema changes I just have to make the change only in this service.
The other services which will be exposed through an API-gateway will be using this database-service as a Lambda Layer.
parent-project
|
|---database-service
|
|---API-service1
|
|---API-service2
...
The Problem is I need to create the tables before any of the Lambda Service is deployed. So that this API-Services can use them. One way to solve this is to deploy the database-service as a Lambda function and invoke the function which will call a method like below to create all the tables.
#SpringBootApplication
public class DatabaseServiceApplication implements CommandLineRunner {
private DynamoDBMapper dynamoDBMapper;
private final AmazonDynamoDB amazonDynamoDB;
public DatabaseServiceApplication(AmazonDynamoDB amazonDynamoDB) {
this.amazonDynamoDB = amazonDynamoDB;
}
public static void main(String[] args) {
SpringApplication.run(DatabaseServiceApplication.class, args);
}
#Override
public void run(String... strings) {
dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
CreateTableRequest tableRequest = dynamoDBMapper
.generateCreateTableRequest(Association.class);
tableRequest.setProvisionedThroughput(
new ProvisionedThroughput(1L, 1L));
TableUtils.createTableIfNotExists(amazonDynamoDB, tableRequest);
}
}
Or use a script to create the tables. I am not sure which is a better option or is there any better option.
Can anyone suggest me if anyone has faced this problem before and fixed it?
To me the best way to do this is on Lambda cold start. Your code needs to be smart enough to not care if the DB is already correct. Based on the code you're showing I would do something on the order of:
public class LambdaExample implements RequestStreamHandler {
// only called on cold start
public LambdaExample() {
dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
CreateTableRequest tableRequest = dynamoDBMapper
.generateCreateTableRequest(Association.class);
tableRequest.setProvisionedThroughput(
new ProvisionedThroughput(1L, 1L));
TableUtils.createTableIfNotExists(amazonDynamoDB, tableRequest);
}
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) {
// handle request. this lambda type requires reading the inputStream
// yourself but use whatever you normally have here.
}
If you're using a traditional relational database, you could use Flyway instead. It too knows if a DB has already been updated.
Note that if you have thousands of Lambdas they will all call this, slowing the cold start of every single one of them. That is why #MarkB is suggesting a process to externalize the DB creation as really only the very first Lambda kicked off does anything useful. After that you're wasting a bit of time/money with every new Lambda.
Since you are deploying via Terraform then the correct way to do this is to have Terraform create the DynamoDB tables as well. You would configure your aws_lambda_function resources in Terraform with depends_on property referencing the aws_dynamodb_table resource, so that Terraform would ensure the table is created before the Lambda functions.
Can you please answer the below questions?
1) Are you deploying your springboot application in lambda?
If Yes, that doesn't sound like a good use of Springboot, Springboot application should be hosted in EC2/ECS instance to be up and running (24/7).
Think about Lambda as a function that runs to handle a simple task. To achieve that, you can write a simple Java application, and deploy the jar to lambda function.
2) CloudFormation, TerraForm and other languages are used to create the infrastructure, you usually run the infrastructure job first, and the deployment after it.
Here's a link of a terraform structure I built for a personal project.
https://github.com/saifmasadeh/terraform-project-structure
Lets say I have a Jersey-service inside a grizzles server and I like to share data between the server and the service-implementation (e.g. mydata).
public class MyServer
{
String mydata="";
public static void main (String [] args)
{
ResourceConfig rc = new ResourceConfig ().packages (MyServer.class.getPackage ().getName ());
HttpServer hs = GrizzlyHttpServerFactory.createHttpServer (URI.create ("http://localhost/myserver"), rc);
for (int i = 0; i < 10; i ++)
{
mydata += "bla";
}
hs.shutdown ();
}
}
#Path ("myservice")
public class MyService
{
#GET
public String getIt()
{
// how to access mydata?
}
}
Whats the best way to share that data?
I can think of a singleton or make mydata static. But maybe there is a standard-way I do not see here?
Thanks!
You can make mydata static or instance variable of singleton if and only if mydata is really static and cannot be changed by multiple threads (e.g. inside your getIt() method of the service).
Such technique applies and uses usually for common configuration properties.
In general it is a standard way for such situation. BTW you can keep your mydata not necessary in the Server class, but make another class to keep such common data there (if there are bunch of them) , but it is a matter of choice.
Also it is more standard to do not make actual mydata field public , but provide getter/setter pair for it.
Finally, if such common/static value can be changed by multiple threads you need to make it synchronized to avoid concurrent modifications.
There are much more different approaches to handle concurrency and make code thread-safe, but it belongs to your actual needs. Anyway all of them end up to static/singleton synchronized implementation.
PS. Be careful, if it is a common static data you have to populate it before start the server not after (as in your example) - otherwise there is a possibility that request may come before data ready to use by service thread.
I am trying to build my first android app. I have multiple Activities and I am using a Handler and an AssetFileDescriptor in order to play a sound file.
My problem is, how can I pass these objects around? I have one Activity that starts a timer via the handler, and another which stops the timer via the handler. Should I pass these objects around between Activities, or is there another way?
I am not used to Java, but I was wondering if I could make a config static class or something that creates all of these objects, and then each one of my Activities would just access these objects from this static config class. However, this has its own problems, since in order to call the method getAssets(), I cannot use a static class ("Cannot make a static reference to a non-static method.")
Any ideas?
This simplest solution would be to store objects in the Application class, here is a SO answer on the topic Using the Android Application class to persist data
Another more advanced option would be to use Dagger. It is a Dependency Injection framework that can do a lot of cool stuff but is somewhat difficult to get running (atleast took me some time to get working).
Dagger enables defining a Singleton class like this:
#Singleton
public class MySingletonObject {
#Inject
MySingletonObject() {
...
}
}
And whenever you need it in your app:
public class SomeActivityOrFragment {
#Inject MySingletonObject mySingletonObject;
...
mySingletonObject.start();
}
public class SomeOtherActivityOrFragment {
#Inject MySingletonObject mySingletonObject;
...
mySingletonObject.stop();
}
I would like to store some data in a static variables and I want all the webservices deployed on the same JBOSS7 to reach those data. I thought a standalone JBOSS runs in a single JVM and all the services run in the same JVM so they can access a static variable.
However I noticed that I got a NullPointerException when my webservice try to get the data.
This is my storage class:
public enum OneJvmCacheImpl {
INSTANCE;
private ConcurrentHashMap<String, Object> values = new ConcurrentHashMap<String, Object>();
public <T> T get(String key, Class<T> type) {
return type.cast(values.get(key));
}
...
}
OneJvmCacheImpl.INSTANCE.get(...);
Can you please advise me why I cannot access the values from my webservice?
Thanks,
V.
If you by deployments mean separate war files, the static variables will not be visible to the other webservices in other war files as they are loaded by different classloaders. Each war has it's own classloader, and hence it's own "class instance" of the class. You could perhaps solve it by moving the class in question to a place where it's shared amongst the deployments, but I would suggest that you solve it otherwise anyway, either by using the database or a distributed cache.
jBoss definitely won't allow you to share static variables across different deployments. That would be a huge security issue, what if I deploy a war next to yours and start changing your static variables...
You need to persist such values in something else like a database, memcache or shared file.
At many places in my web application I need a certain String which is :
request.getServletContext().getRealPath("/");
// I can only get this once the web-app starts
Sometimes a simple java class needs to know this string. I don't want to pass each and every time this string to the class's function. One way could be to stash this string in a file at the very beginning of the web application. Every time I would need this, simply read the file.But this doesn't seem a pretty good option. Is there any other way out ?
May be I can store in the context.xml of the application. If it is possible how do I do that ?
If there is a better way please suggest.
I am using tomcat as the server.
Invoke run the following code when your application starts (e.g. with a ServletContextListener):
public void contextInitialized(ServletContextEvent sce) {
ServletContextRootRealPath.set(sce.getServletContext().getRealPath("/"));
}
Then later whenever you need it you simply call
ServletContextRootRealPath.get()
Since it's all static the variable is accessible JVM-wide to every code that runs in this JVM.
Utility class
public final class ServletContextRootRealPath {
private static String path;
private ServletContextRootRealPath() {
// don't instantiate utility classes
}
public static void set(String rootRealPath) {
path = rootRealPath;
}
public static String get() {
return path;
}
}
You can store the value in static variable of any class (Basically a helper class which is used for serving common utility functions). Later you can refer to this variable without creating instance of the class, as it is static and can be accessed without its instance.