How to load a ogm.properties file in a spring project when I want to connect to Neo4J Database? - spring-data-neo4j

First of all , If I put the ogm.properties into the resources folder , it worked well .
But if I put the ogm.properties into resources/neo4j folder , it didn't work and show the Exception called org.neo4j.ogm.exception.ServiceNotFoundException: Driver: null
I had figured out that 'spring-data-neo4j' jar default to load the ogm.properties under the classpath , not a customized path like what the picture show .
So , I want to ask that how to make it could worked by using the path:resources/neo4j/ogm.properties instead of using the path:resources/ogm.properties .

You should create the Configuration object manually and provide the config file from your class path like this:
new Configuration.Builder(new ClasspathConfigurationSource("/neo4j/ogm.properties"))
// more configuration if needed
.build();
So a minimal example for your Spring configuration could be:
#Bean
public SessionFactory getSessionFactory() {
return new SessionFactory(configuration(), "com.myapp...");
}
#Bean
public Configuration configuration() {
return new Configuration
.Builder(new ClasspathConfigurationSource("/neo4j/ogm.properties"))
.build();
}

Related

Importing secrets in Spring Boot application from AWS Secrets Manager

I stored my MySQL DB credentials in AWS secrets manager using the Credentials for other database option. I want to import these credentials in my application.properties file. Based on a few answers I found in this thread, I did the following:
Added the dependency spring-cloud-starter-aws-secrets-manager-config
Added spring.application.name = <application name> and spring.config.import = aws-secretsmanager: <Secret name> in application.properties
Used secret keys as place holders in the following properties:
spring.datasource.url = jdbc:mysql://${host}:3306/db_name
spring.datasource.username=${username}
spring.datasource.password=${password}
I am getting the following error while running the application:
java.lang.IllegalStateException: Unable to load config data from 'aws-secretsmanager:<secret_name>'
Caused by: java.lang.IllegalStateException: File extension is not known to any PropertySourceLoader. If the location is meant to reference a directory, it must end in '/' or File.separator
First, is the process I am following correct? If yes, what is this error regarding and how to resolve this?
I found the problem that was causing the error. Apparently I was adding the wrong dependency.
According to the latest docs, the configuration support for using spring.config.import to import AWS secrets has been moved to io.awspring.cloud from org.springframework.cloud. So the updated dependency would be io.awspring.cloud:spring-cloud-starter-aws-secrets-manager-config:2.3.3 and NOT org.springframework.cloud:spring-cloud-starter-aws-secrets-manager-config:2.2.6
You are trying to use spring.config.import, and the support for this was introduced in Spring Cloud 2.3.0:
https://spring.io/blog/2021/03/17/spring-cloud-aws-2-3-is-now-available
Secrets Manager
Support loading properties through spring.config.import, introduced in Spring Cloud 2020.0 Read more about integrating your
Spring Cloud applicationwiththe AWS secrets manager.
Removed the dependency to auto-configure module #526.
Dropped the dependency to javax.validation:validation-api.
Allow Secrets Manager prefix without “/” in the front #736.
In spring-cloud 2020.0.0 (aka Ilford), the bootstrap phase is no
longer enabled by default. In order enable it you need an additional
dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>{spring-cloud-version}</version>
</dependency>
However, starting at spring-cloud-aws 2.3, allows import default aws'
secretsmanager keys (spring.config.import=aws-secretsmanager:) or
individual keys
(spring.config.import=aws-secretsmanager:secret-key;other-secret-key)
https://github.com/spring-cloud/spring-cloud-aws/blob/main/docs/src/main/asciidoc/secrets-manager.adoc
application.yml
spring.config.import: aws-secretsmanager:/secrets/spring-cloud-aws-sample-app
Or try to leave it empty:
spring.config.import=aws-secretsmanager:
As such, it will take spring.application.name by default,
App:
#SpringBootApplication
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
#Bean
ApplicationRunner applicationRunner(#Value("${password}") String password) {
return args -> {
LOGGER.info("`password` loaded from the AWS Secret Manager: {}", password);
};
}
}

Angular 6 unit test - TypeError: Cannot read property 'ROOT_API' of null

I am getting an error while running a unit test in my angular project
TypeError: Cannot read property 'ROOT_API' of null
I am using "app.config" for the environment files to keep its assets folder and call the service. In the component call the API and work without any problem but while running unit test getting the error above mentioned.
Here are my files and folder structure
Here is the adaptor service file get method
Here is the service file
Unit test error screenshot below
Please help me out with the issue. Thanks
Make sure to Provide AppConfig, in the TestBed configuration of your test.
(It would be helpful if you post your test, as well).
In your AppConfig File changed the private value for empty and remove the null value.
private config: Object = '';
private env: Object = '';
It's working fine for me....

ef core migration can't use secret manager

When I create .net core web applications, I use the secret manager during testing. I am generally able to create a new web project (mvc and web api), right click on the project and select "manage user secrets". This opens a json file where I add the secrets. I then use this in my startup.cs something like this:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySql(Configuration["connectionString"]));
The website works fine with this and connects well to the database. However when I try using ef core migration commands such as add-migration, they don't seem to be able to access the connection string from the secret manager. I get the error saying "connection string can't be null". The error is gone when I hard code Configuration["connectionString"] with the actual string. I have checked online and checked the .csproj file, they already contain the following lines:
<UserSecretsId>My app name</UserSecretsId>
And later:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.1" />
<DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" />
Is there anything I need to add so the migrations can access the connection string?
Update
I only have one constructor in the context class:
public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options)
{
}
I am currently coming across this exact problem as well. I have come up with a solution that works for now, but one may consider messy at best.
I have created a Configuration Class that provides the Configuration Interface when requested:
public static class Configuration
{
public static IConfiguration GetConfiguration()
{
return new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.AddUserSecrets<Startup>()
.AddEnvironmentVariables()
.Build();
}
}
In the Migration, you can then get the Configuration File and access its UserSecrets like this:
protected override void Up(MigrationBuilder migrationBuilder)
{
var conf = Configuration.GetConfiguration();
var secret = conf["Secret"];
}
I have tested creating a SQL Script with these User Secrets, and it works (you obviously wouldn't want to keep the Script laying around since it would expose the actual secret).
Update
The above config can also be set up into Program.cs class in the BuildWebHost method:
var config = new ConfigurationBuilder().AddUserSecrets<Startup>().Build();
return WebHost.CreateDefaultBuilder(args).UseConfiguration(config)...Build()
Or in the Startup Constructor if using that Convention
Update 2 (explanation)
It turns out this issue is because the migration scripts runs with the environment set to "Production". The secret manager is pre-set to only work in "Development" environment (for a good reason). The .AddUserSecrets<Startup>() function simply adds the secrets for all environment.
To ensure that this isn't set to your production server, there are two solutions I have noticed, one is suggested here: https://learn.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell
Set env:ASPNETCORE_ENVIRONMENT before running to specify the ASP.NET Core environment.
This solution would mean there is no need to set .AddUserSecrets<Startup>() on every project created on the computer in future. However if you happen to be sharing this project across other computers, this needs to be configured on each computer.
The second solution is to set the .AddUserSecrets<Startup>() only on debug build like this:
return new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
#if DEBUG
.AddUserSecrets<Startup>()
#endif
.AddEnvironmentVariables()
.Build();
Additional Info
The Configuration Interface can be passed to Controllers in their Constructor, i.e.
private readonly IConfiguration _configuration;
public TestController(IConfiguration configuration)
{
_configuration = configuration;
}
Thus, any Secrets and Application Setting are accessible in that Controller by accessing _configuration["secret"].
However, if you want to access Application Secrets from, for example, a Migration-File, which exists outside of the Web Application itself, you need to adhere to the original answer because there's no easy way (that I know of) to access those secrets otherwise (one use case I can think of would be seeding the Database with an Admin and a Master Password).
To use migrations in NetCore with user secrets we can also set a class (SqlContextFactory) to create its own instance of the SqlContext using a specified config builder. This way we do not have to create some kind of workaround in our Program or Startup classes. In the below example SqlContext is an implementation of DbContext/IdentityDbContext.
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
public class SqlContextFactory : IDesignTimeDbContextFactory<SqlContext>
{
public SqlContext CreateDbContext(string[] args)
{
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
.AddUserSecrets<Startup>()
.AddEnvironmentVariables()
.Build();
var builder = new DbContextOptionsBuilder<SqlContext>();
builder.UseSqlServer(config.GetConnectionString("DefaultConnection"));
return new SqlContext(builder.Options);
}
}
Since I have noticed a lot of people running into this confusion, I am writing a simplified version of this resolution.
The Problem/Confusion
The secret manager in .net core is designed to work only in the Development environment. When running your app, your launchSettings.json file ensures that your ASPNETCORE_ENVIRONMENT variable is set to "Development". However, when you run EF migrations it doesn't use this file. As a result, when you run migrations, your web app does not run on the Development environment and thus no access to the secret manager. This often causes confusion as to why EF migrations can't use the secret manager.
The Resolution
Make sure your environment variable "ASPNETCORE_ENVIRONMENT" is set to "Development" in your computer.
The way of using .AddUserSecrets<Startup>() will make a circular reference if we having our DbContext in a separate class library and using DesignTimeFactory
The clean way of doing that is:
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
#if DEBUG
.AddJsonFile(#Directory.GetCurrentDirectory() +
"{project path}/appsettings.Development.json",
optional: true, reloadOnChange: true)
#else
.AddJsonFile(#Directory.GetCurrentDirectory() +
"{startup project path}/appsettings.json",
optional: true, reloadOnChange: true)
#endif
.AddEnvironmentVariables()
.Build();
var connectionString = configuration.GetConnectionString("DefaultConnection");
var builder = new DbContextOptionsBuilder<AppDbContext>();
Console.WriteLine(connectionString);
builder.UseSqlServer(connectionString);
return new AppDbContext(builder.Options);
}
}
The Explanation:
Secret Manager is meant to be in the development time only, so this will not affect the migration in case if you have it in a pipeline in QA or Production stages, so to fix that we will use the dev connection string which exists in appsettings.Development.json during the #if Debug.
The benefit of using this way is to decouple referencing the Web project Startup class while using class library as your Data infrastructure.

aws AmazonDynamoDBSessionManagerForTomcat ClassNotFound issue

I have created a simple aws web project using the Eclipse sdk.
I checked on Session Management using dynamo db so that my sessions are not sticky and they can persist if the load balancer adds or removes instances.
This project has a simple Object
package com.ns.ts.dto;
import java.io.Serializable;
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = -7038692393544658830L;
private String user;
private String name;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And there are two servlets, setUser (which takes some parameters and sets user in the session with some values)
and getUser (which displays the user values from the session)
I deploy the project and all seems fine. A table gets created in DynamoDB.
Now I call setUser. This sets the object User in the session with some values.
Next, I call getUser and this displays the values of the User object from the session.
(Seems that the session is still in the EC2 instance)
I wait for some time and again call setUser with a different set of parameters.
I am watching the table in DynamoDB to make sure that the session object is in the table (I confirm this by last updated time for the row)
I wait for some time and again call getUser.
This throws an error:
java.lang.ClassNotFoundException:com.ns.ts.dto.User
The error is generated at
com.amazonaws.tomcatsessionmanager.amazonaws.services.dynamodb.sessionmanager.DynamoDBSessionStore.load
I think this error is generates when the jar tries to deserilize the session object from dynampDB and it cant find the classpath for my custom object in the shared lib of Tomcat.
Is there anybody who has faced this before ?
Is there a work around / solution for using custom objects in a session and store them the dynamoDB ?
If the jar containing your User class is located under the WEB-INF/lib directory of your webapp, try moving it under Tomcat's lib directory. It probably needs to be alongside the Amazon jar for the class loading to work correctly.
There is an update and this problem seems to be have resolved.
https://github.com/aws/aws-dynamodb-session-tomcat/issues/3

Custom Jetty Filters in Dropwizard

I'm attempting to add a custom header filter in my Dropwizard instance to check to see if the request's version is synced to the Dropwizard instance's version.
I see you can use FilterBuilder to add jetty CrossOriginFilters. However, I am having trouble figuring out how to set a custom filter.
Thanks
Via the Environment class.
https://dropwizard.github.io/dropwizard/manual/core.html#environments
#Override
public void run(MyApplicationConfiguration configuration, Environment environment) {
environment.servlets().addFilter("Custom-Filter-Name", new MyCustomFilter()).addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
}
You can choose which Dispatch types by changing EnumSet.allOf(DispatcherType.class)
This is how I got it to work using Dropwwizard 0.7.1 (APIs appear to have changed from other examples I found out there)
In run method of your application:
final FilterRegistration.Dynamic cors = environment.servlets().addFilter("crossOriginRequsts", CrossOriginFilter.class);
cors.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
https://gist.github.com/craigbeck/fb71818063175b9b4210