Integrate Spring-based java module into a standalone java application - java

I have a Spring-based module that I need to integrate with an existing/legacy Java "standalone" app. The Spring-based module is a simple implementation of an AuthenticationProvider (spring-security).
What I would like to do is hook up the spring based module in a Java application in a way that I can simply call the authenticate method on that provider from the Java code.
Is that possible? What is required?
Is it possible to wrap the spring module in a plain Java library and use that as API interface for my standalone Java app?
I already searched for specific tutorials but it seems there isn't one that fit this requirement.

OK, I have to use the ApplicationContext directly so I can manage the Spring framework in my application.
public class MyApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(MyApplication.class);
public static void main(String[] args) {
MyAuthenticationProvider authProvider;
try (ConfigurableApplicationContext springApplicationContext = new AnnotationConfigApplicationContext(
MySpringConfiguration.class)) {
springApplicationContext.registerShutdownHook();
authProvider = springApplicationContext.getBean(MyAuthenticationProvider.class);
}
Authentication request = new UsernamePasswordAuthenticationToken("foo", "foo");
Authentication result = authProvider.authenticate(request);
if (result.isAuthenticated()) {
LOGGER.debug("User is authenticated");
} else {
LOGGER.debug("Cannot authenticate user.");
}
}

Related

Apache Camel File-Watch Without Spring

I am trying to use Apache Camel File-Watch feature.
However I notice all example are used along with Spring.
Is there anyway to make use of this feature without Spring ?
Thank you for any potential input.
Best regards.
Apache Camel is a standalone integration framework to easily integrate different systems using well know and established EIP (Enterprise Integration Patterns).
It is not tied to Spring in any way at its core and has different deployment / integration models out of which is Spring / Spring Boot for the sake of easing its adoption and configuration for Spring framework users.
Out of the runtime contexts, you can use for example Camel Main component to run your application having a File Watch component setup to watch the /tmp/ directory change events:
The main application would look like the following:
public class FileWatchApplication {
private FileWatchApplication() {
}
public static void main(String[] args) throws Exception {
// use Camels Main class
Main main = new Main(FileWatchApplication.class);
// now keep the application running until the JVM is terminated (ctrl + c or sigterm)
main.run(args);
}
}
A simple RouteBuilder setting up your File Watch component would look like the following (note that it must be within the same (or child) package of the FileWatchApplication class):
public class FileWatchRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
// snippet configuration from the official documentation
from("file-watch:///tmp/")
.log("File event: ${header.CamelFileEventType} occurred on file ${header.CamelFileName} at ${header.CamelFileLastModified}");
}
}
Camel is based on Spring. In fact, the Camel Context is an extension of the Spring Application Context. So if you have Camel, you also must have Spring.

Keyvault MSI with Spring boot : How to config keyvault to use Azure cli credentials instead of managed identity while running on local?

I created a simple spring boot app to retrieve secrets from keyvault.
I added the following dependency to work around with,
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-boot-starter-keyvault-secrets</artifactId>
<version>3.5.0</version>
</dependency>
and added the following in application.properties
azure.keyvault.enabled=true
azure.keyvault.uri=<URL>
#keys
mySecretProperty=secret
and my main application,
#SpringBootApplication
public class KeyVaultSample implements CommandLineRunner {
#Value("${mySecretProperty}")
private String mySecretProperty;
public static void main(String[] args) {
SpringApplication.run(KeyVaultSample.class, args);
}
#Override
public void run(String... args) {
System.out.println("property your-property-name value is: " + mySecretProperty);
}
}
But every time I tried to run the above app on local, it tries to use ManagedIdentityCredential to connect. So I added a configuration class for creating a bean for SecretClient with AzureCliCredential, but then too, the results are the same.
My Configuration class,
#Configuration
public class AppConfiguration {
#Bean
public SecretClient secretClient() {
AzureCliCredential az = new AzureCliCredentialBuilder().build();
SecretClient sec = new SecretClientBuilder().vaultUrl("<url>")
.credential(az).buildClient();
return sec;
}
}​
I'm looking for ways I could use/test this keyvault on my local.
Is there any configuration I could put in the properties file which would make it use AzureCliCredential instead of ManagedIdentityCredential?
azure-spring-boot-starter-keyvault-secrets uses MSI / Managed identities.
If you would like to authenticate with Azure CLI, just use azure-identity and azure-security-keyvault-secrets.
public void getSecretWithAzureCliCredential() {
AzureCliCredential cliCredential = new AzureCliCredentialBuilder().build();
// Azure SDK client builders accept the credential as a parameter
SecretClient client = new SecretClientBuilder()
.vaultUrl("https://{YOUR_VAULT_NAME}.vault.azure.net")
.credential(cliCredential)
.buildClient();
KeyVaultSecret secret = secretClient.getSecret("<secret-name>");
System.out.printf("Retrieved secret with name \"%s\" and value \"%s\"%n", secret.getName(), secret.getValue());
}
If you don't necessarily need the real thing in local (a test double can be fine instead of Azure Key Vault) you could try Lowkey Vault too! It supports keys and secrets using a local container and you can fake the authentication using a simple basic auth.
Project home: https://github.com/nagyesta/lowkey-vault
Java POC (although not using the Spring Boot starter): https://github.com/nagyesta/lowkey-vault-example

What is the best way to switch AWSCredentialsProviders?

I am writing a Java application that users Spring for dependency injection and AWS for various services. I will be deploying the application to EC2. The issue I am having is setting the AWS credentials in a secure way during development/deployment. Because the service is running on EC2, I would like to use the InstanceProfileCredentialsProvider in production. However, these credentials are not available during development.
Almost all the AWS clients are currently injected using Spring. Here is an example using DynamoDB:
#Lazy
#Configuration
public class SpringConfiguration {
#Bean(name = "my.dynamoDB")
public DynamoDB dynamoDB() {
return DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
new AWSCredentialsProvider() /* What should go here? */));
}
}
Any thoughts?
Try creating a separate bean that returns a credentials provider. Within that method switch between the two credential sources based on stage or host type.
/**
* #return: an AWSCredentialsProvider appropriate for the stage.
*/
#Bean
public AWSCredentialsProvider awsCredentialsProvider() {
if(isProd() /* define what this means in your configuration code */) {
return new InstanceProfileCredentialsProvider()
} else {
return new AWSCredentialsProvider()
}
}

How do I get BundleContext in the other classes which is not starting the framework?

I have recently started using OSGi framework. I am trying to launch an OSGi framework from Java main application. I was following this tutorial to embed OSGI container into my project.
Below is my Java main application which I am using to launch an OSGi container. In the below class, I am able to get BundleContext using the framework object and then I can use this BundleContext to install actual OSGi bundles.
public class OSGiBundleTest1 {
public static Framework framework = null;
public static void main(String[] args) throws BundleException {
FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
Map<String, String> config = new HashMap<String, String>();
framework = frameworkFactory.newFramework(config);
framework.start();
callMethod();
callMethodOfAnotherClass();
}
private static void callMethodOfAnotherClass() {
OSGiBundleTest2 ss = new OSGiBundleTest2();
ss.someMethod();
}
private static void callMethod() throws BundleException {
BundleContext context = framework.getBundleContext();
System.out.println(context);
}
}
Now this is my second class in the same maven based project. And I need to use BundleContext here as well. So I thought I can use FrameworkUtil.getBundle(OSGiBundleTest2.class).getBundleContext() to get the BundleContext but it is not working here and I get NPE there. So that means, this class is not loaded by OSGi classloader. So now what is the best way to use BundleContext in the below class.
public class OSGiBundleTest2 {
public OSGiBundleTest2() {
}
public static void callMethodOfAnotherClass() {
System.out.println(FrameworkUtil.getBundle(OSGiBundleTest2.class));
BundleContext bundleContext = FrameworkUtil.getBundle(OSGiBundleTest2.class).getBundleContext();
}
}
callMethodOfAnotherClass will get called from the OSGiBundleTest1 class. I am not thinking of passing framework object to the constructor of OSGiBundleTest2 class or some method to use the framework object and then get the BundleContext from there... Is there any other way to do this thing?
Any way to make sure all the classes get loaded by OSGI classloader only?
The way to make sure classes get loaded by an OSGi classloader is to put them in bundles and actually use OSGi to load them.

ClassLoader problem when using GWT RequestFactory with Grails

In order to get GWT RequestFactory running with Grails, I am using the following approach:
class GwtController extends RequestFactoryServlet {
public GwtController() {
super()
}
def index = {
doPost request, response
}
#Override
public ServletContext getServletContext() {
return ServletContextHolder.servletContext
}
#Override
public ServletConfig getServletConfig() {
return new DummyServletConfig(getServletContext(),"grails");
}
}
where DummyServletConfig is a simple implementation of ServletConfig
This is working when deploying the app to tomcat. However, using testing or development mode, it is not. I was required to adjust the GWT Servlet in order to prevent it from using the wrong Class Loader:
In line 46 I changed
private static final RequestFactoryInterfaceValidator validator =
new RequestFactoryInterfaceValidator(log,
new RequestFactoryInterfaceValidator.ClassLoaderLoader(
ServiceLayer.class.getClassLoader()));
to
private static final RequestFactoryInterfaceValidator validator = new RequestFactoryInterfaceValidator(
log, new RequestFactoryInterfaceValidator.ClassLoaderLoader(
Thread.currentThread()
.getContextClassLoader()));
Otherwise, it wouldn't find my Domain classes (which apparently do not reside in the GrailsRootLoader but in the Thread's class loader).
Now I would like to revert my GWT servlet to the official binary released by Google and I wonder how I can fix the incorrect ClassLoader in Grails or make the RequestFactoryServlet work correctly without altering the GWT source.
I hope that GWT 2.3 will fix your problem:
http://code.google.com/p/google-web-toolkit/issues/detail?id=6092

Categories