How to get applicationContextPath in dropwizard 1.0.0 - java

We are using server configuration in yml file which looks like as below
server:
type: simple
connector:
type: http
port: 8061
applicationContextPath: /administration
adminContextPath: /admin
#disable the registration of default Jersey ExceptionMappers
registerDefaultExceptionMappers: false
I want to get "applicationContextPath" when I start my dropwizard service.
I am trying to get it using
environment.getApplicationContext().getContextPath();
but I am getting "/" i.e. default value. Is there anyway to get this.

In order get applicationContextPath we need to get ServerFactory from Configuration and parse it to SimpleServerFactory as below:
((SimpleServerFactory) getConfiguration().getServerFactory()).getApplicationContextPath()

This works for me:
#Override
public void run(CustomAppConfiguration customAppConfiguration , Environment environment) throws Exception {
DefaultServerFactory factory = (DefaultServerFactory) customAppConfiguration .getServerFactory();
System.out.println("CONTEXT PATH: "+factory.getApplicationContextPath());
...
}

If it's in your config file and you want to just read the value in as it exist in your config.yml, then I'd suggest making it part of your Configuration class. Values in your config can always be accessed this way regardless of whether dropwizard uses and treats those key/values in special manner internally.
The following worked for me in dropwizard 1.0.0:
MyApp.java:
public class MyApp extends Application<MyConfig> {
//...
#Override
public void run(MyConfig configuration, Environment environment) throws Exception {
System.out.println(configuration.contextPath);
//...
MyConfig.java
public class MyConfig extends Configuration {
//...
#JsonProperty("applicationContextPath")
public String contextPath;
//...

If I understood your question correctly what you can do in Dropwizard version 1.3.8 if you are using simple server (without https) you can get applicationContextPath in following way:
server:
type: simple
rootPath: /*
applicationContextPath: /administration
adminContextPath: /admin
connector:
type: http
port: 8080
More info about rootPath can be found in Dropwizard Configuration Reference. So if you want to access:
Application REST endpoint /books (which is value of GET,
POST or similar annotation in one of your Resource class methods) you can
type URL like this http://localhost:8080/administration/books
Metrics (only accessible via admin context path) of your Dropwizard application then you create URL like this: http://localhost:8080/admin/metrics
Hope that helps. Cheers!

Related

Unable to create camel salesforce endpoint

I am trying to connect to salesforce using Apache Camel salesforce component.
Here is a very simple route I am trying to start:
#Override
public void configure() throws Exception {
from("salesforce:event/Case__e")
.to("mock:end");
}
When trying to start it I am getting an obvious error saying I did not specify a client id:
Caused by: java.lang.IllegalArgumentException: clientId must be specified
at org.apache.camel.util.ObjectHelper.notNull(ObjectHelper.java:149) ~[camel-util-3.16.0.jar:3.16.0]
at org.apache.camel.component.salesforce.SalesforceLoginConfig.validate(SalesforceLoginConfig.java:238) ~[camel-salesforce-3.16.0.jar:3.16.0]
That makes perfectly sense as according to Camel docs clentId parameter must be specified. To address this I am specifying a clientId as below:
#Override
public void configure() throws Exception {
from("salesforce:event/Case__e?clientId=xyz")
.to("mock:end");
}
When trying to start the route this time I am getting a rather strange error complaining about clientId being an unknown parameter:
Failed to resolve endpoint: salesforce://event/Case__e?clientId=xyz due to: There are 1 parameters that couldn't be set on the endpoint.
Check the uri if the parameters are spelt correctly and that they are properties of the endpoint.
Unknown parameters=[{clientId=xyz}]
Not sure what I am doing wrong and how should I address this.
Thank you in advance for your inputs.
Your problem is related to the fact that clientId is a component option so it must be configured at the component level while you try to configure it like it was a query parameter / an endpoint option which cannot work.
Depending on the runtime that you use, the way to configure a component may change but the idea remains the same.
For example, assuming that you use an application.properties to configure your application, the configuration of your salesforce component would look like this:
In application.properties
# Salesforce credentials
camel.component.salesforce.login-config.client-id=<Your Client ID>
camel.component.salesforce.login-config.client-secret=<Your Client Secret>
camel.component.salesforce.login-config.refresh-token=<Your Refresh Token>
...
Here is a salesforce example https://github.com/apache/camel-examples/blob/main/examples/salesforce-consumer/

Spring cloud config - Share file or his location

I have two applications :
one spriig boot config server
the another one a spring boot config client
The client side have to use a file named certificate.json.
I want to store this file in the server side so another microprogram and my client programm who need it can retrieve it from the server side.
I try that :
copy the file certificate.json to classpath:/config
add this line to the application.properties :
certificate.location: classpath:config/certificate.json
call the value from client programm by :
#Value("${certificate.location}")
private String certificateLocation;
But the value of certificateLocation is classpath:config/certificate.json. The value I want is the file location like : /home/user/project/scr/main/resources/config/certificate.json.
Or, are there a way to directly retrieve my file by URI, for example locahost:8889/... (8889 is my config server port).
EDIT 1:
I cannot use absolute path from the server because I'm not the one who run it.
Thank you in advance.
I'd do
#Value("${certificate.location}") private Resource certificateLocation;
that way, your location is already a Resource that you can load, call getURI(), getFile().getAbsolutePath() etc. Since your value is prefixed with classpath:, you would have a ClassPathResource instance, which you can use for lot of things.
The classpath is just a protocol part of the URL. You can use file or any other supported protocol. For example, file://home/user/project/scr/main/resources/config/certificate.json.
Try this url
spring.cloud.config.server.native.searchLocations
=file://${user.home}/CentralRepo/
SPRING_PROFILES_ACTIVE=native
I am also get this way using microservice
OP you need to create a web service and return certificate.json as the response. Then you can send and receive data by sending a GET or POST request to a URI like https://12.12.12.12:8080/getCertificate. Please see:
https://spring.io/guides/gs/rest-service/
As a side note, you should never expose your inner files to the internet because it's very unsecure and opens you up to pirating and hacking.
What I would do in this case is
Add configuration for static folder
#SpringBootApplication public class DemoStaticresourceApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(DemoStaticresourceApplication.class, args);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**").addResourceLocations("file:/fileFolder/")
.setCachePeriod(0);
}
}
Place certificate.json in fileFolder and try http://localhost:8080/files/certificate.json and it will be served directly from file system for you.
And now every file you add in this folder will be served only if called using /files/ path

Why does Restlet on GAE says Component is NULL

On every request made to the Restlet resources, I see the following logs in Google App Engine Logs
21:38:50.059 javax.servlet.ServletContext log: ExampleAPIs: [Restlet] ServerServlet: component class is null
21:38:51.568 javax.servlet.ServletContext log: ExampleAPIs: [Restlet] Attaching application: com.example.api.ExampleAPIConfig#68ec99 to URI: /example/v1
Why does it say Component is null?
I agree that I did not define Components rather used ServerResources and mapped them to the router in the Application class. But thats how it is supposed to be done as per the Restlet GAE Edition documentation.
Application class for wiring routes
public Example extends Application {
#Override
public Restlet createInboundRoot() {
router = new Router(getContext());
CorsService corsService = new CorsService();
corsService.setAllowedOrigins( new HashSet<String>(Arrays.asList("http://example.com")));
corsService.setAllowedCredentials(true);
getServices().add(corsService);
router.attach("/xyz", XYZ.class);
}
}
Server Resource which handles and returns a JSON Representation
public class XYZ extends ServerResource {
private static final Logger logger = Logger.getLogger("API:Xyz");
#Get(":json")
public Representation handleGetRequest() {
..
return new JsonRepresentation("{\"code\": 4008, \"description\": \"Something blah something\"}");
}
}
Is there something I am doing wrong ?
Did you configure your servlet configuration file as explained in document (below link).
I think servlet is not bound to a class.
https://restlet.com/technical-resources/restlet-framework/guide/2.3/editions/gae
Update
Ok so if you deeper in documentation :
https://restlet.com/technical-resources/restlet-framework/javadocs/2.0/jee/ext/org/restlet/ext/servlet/ServerServlet.html
https://restlet.com/technical-resources/restlet-framework/javadocs/2.0/jee/api/org/restlet/Component.html
You can see that component is optional but can be usefull, but maybe in GAE implementation it doesn't have one by default.

dropwizard: read configuration from a non-file source

What's the right way to read configuration in dropwizard from something like a database, or a REST call? I have a use case where I cannot have a yml file with some values, and should retrieve settings/config at startup time from a preconfigured URL with REST calls.
Is it right to just invoke these REST calls in the get methods of the ApplicationConfiguration class?
Similar to my answer here, you implement the ConfigurationSourceProvider interface the way you wish to implement and configure your dropwizard application to use it on your Application class by:
#Override
public void initialize(Bootstrap<MyConfiguration> bootstrap){
bootstrap.setConfigurationSourceProvider(new MyDatabaseConfigurationSourceProvider());
}
By default, the InputStream you return is read as YAML and mapped to the Configuration object. The default implementation
You can override this via
bootstrap.setConfigurationFactoryFactory(new MyDatabaseConfigurationFactoryFactory<>());
Then you have your FactoryFactory :) that returns a Factory which reads the InputStream and returns your Configuration.
public T build(ConfigurationSourceProvider provider, String path {
Decode.onWhateverFormatYouWish(provider.open(path));
}
elaborating a bit further on Nathan's reply, you might want to consider using the UrlConfigurationSourceProvider , which is also provided with dropwizard, and allows to retrieve the configuration from an URL.
Something like:
#Override
public void initialize(Bootstrap<MyRestApplicationConfiguration> bootstrap) {
bootstrap.setConfigurationSourceProvider(new UrlConfigurationSourceProvider());
}

Sample SAML Java Config. Project, Broken From the Start

I pulled in the example Java configuration project for Spring's SAML extension. No commits seem to have been made to the project for about six months as of my writing this question. I have not done anything to this project except for run maven package against it.
I then run the application in Spring Tool Suite as a Spring Boot Application and the application runs; however, the application does not run without error and the application endpoint is inaccessible (resulting in am error message): "ERROR: Something went wrong in the authentication process".
I haven't registered any certificates, etc (and may very well need to). There are no instructions provided with the GitHub project for starting or working with the application. I have intentionally not posted the guts of the project as I have left it unmodified.
INFORMATION ON THE ERROR
From Chrome Dev. Tools, I can see a 500 Internal Server Error returned from the request to the localhost:8080 application. So, the issue is definitely with the sample application (or something that I have not done).
The following error is logged to the console on application deployment (I've included both an image and the text as the text is proving difficult to format):
Text:
[2015-08-20 14:41:40.551] boot - 9908 INFO [localhost-startStop-1]
--- HttpMethodDirector: I/O exception (javax.net.ssl.SSLPeerUnverifiedException) caught when processing
request: SSL peer failed hostname validation for name: 46.4.112.4
[2015-08-20 14:41:40.551] boot - 9908 INFO [localhost-startStop-1]
--- HttpMethodDirector: Retrying request
[2015-08-20 14:41:40.795] boot - 9908 ERROR [localhost-startStop-1] --- HTTPMetadataProvider:
Error retrieving metadata from https://idp.ssocircle.com/idp-meta.xml
javax.net.ssl.SSLPeerUnverifiedException: SSL peer failed hostname
validation for name: 46.4.112.4
at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.verifyHostname(TLSProtocolSocketFactory.java:233)
at
org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:194)
I have visited the url endpoint provided by ssocircle and the metadata is exposed.
If I visit the /saml/metadata endpoint of the service provider and get some helpful information: an org.opensaml.saml2.metadata.provider.MetadataProviderException exception. The description if which is "No IDP was configured, please update included metadata with at least one IDP"; however, the source of this may be the above described error.
QUESTION
Am I missing something that is readily apparent to start the example application? In other words, what does this error tell me that I need to be investigating? Or, as it is "non-breaking", do I ignore it?
WHY I'M ASKING
The documentation surrounding the deployment of the Sample Java Configuration application is minimal (as in "non-existant"). The self-documentation only provides "hints", such as the following:
// IDP Metadata configuration - paths to metadata of IDPs in circle of trust is here
// Do no forget to call initialize method on providers
#Bean
#Qualifier("metadata")
public CachingMetadataManager metadata() throws MetadataProviderException {
List<MetadataProvider> providers = new ArrayList<MetadataProvider>();
providers.add(ssoCircleExtendedMetadataProvider());
return new CachingMetadataManager(providers);
}
I am certain there is something I am not doing, particularly since I have not done anything in the deployment of the application except for the run of the mvn package, described above.
The problem occurs due to the sample application's utilization of a deprecated constructor - a deprecation whose warning was explicitly suppressed - for the HTTPMetadataProvider (a fix I will commit, shortly). In configuring the ExtendedMetadataDelegate, the two-parametered constructor is utilized:
#Bean
#Qualifier("idp-ssocircle")
public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider() throws MetadataProviderException {
#SuppressWarnings({ "deprecation"})
HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider("https://idp.ssocircle.com/idp-meta.xml", 5000);
// other config.s...
}
If replaced with the non-deprecated constructor that takes a java.util.Timer and an org.apache.commons.httpclient.HttpClient (in addition to the metadata url), the sample application works, beautifully, and no errors are logged.
Additional Non-OP-related Information
I had to do the below to get the Sample SAML app to run
After removing the deprecated constructor, I recommend doing two things:
Follow the steps outlined in 4.2.6 of the documentation, i.e. treat the application during setup as the XML-configured application. All the steps need to be taken to "register" the metada.The application will be unable to register its metadata with the current Java configuration (see below; point no. 2)
Change the default configurations in class WebSecurityConfig (read detail, below)
Configuration Change
In the configuration of the ExtendedMetadataDelegate bean ssoCircleExtendedMetadataProvider, change the ExtendedMetadataDelegate's property values as follows:
// code....
extendedMetadataDelegate.setMetadataTrustCheck(true);
extendedMetadataDelegate.setMetadataRequireSignature(false);
// code....
In the ExtendedMetadata bean (different from above), change the property values as below:
// code....
extendedMetadata.setIdpDiscoveryEnabled(true);
extendedMetadata.setSignMetadata(false);
// code....
"Disclaimer"
Whether or not this should be used in production, I do not know; however, it seems to better reflect both the XML-based configuration and resulting metadata of the XML-configured Service Provider example referenced in the SAML Spring Documentation
Just some hints:
I met this exception when I was trying to set up the HTTP-Artifact profile.
There is a hostnameVerifier in org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory (openws-1.5.1) and a verifyHostname() processing before OpenSAML tries to create socket to connect to other host.
I configured sslHostnameVerification to "allowAll" in org.springframework.security.saml.metadata.ExtendedMetadata, the allowed values are "default", "defaultAndLocalhost", "strict", and "allowAll".
It seems in your case, this exception was thrown when the SP (your saml sample) was trying to download the metadata.xml from IdP (ssocircle). The best way to figure out what is happening is to debug when and where the hostnameVerifier was set.
Or you can try set sslHostnameVerification to "allowAll" in the SSOCircle's ExtendedMetadataDelegate's ExtendedMetadata to have a try first..
checkout this answer: It basically describes a plugin I recently released that allows you to configure Spring Boot and Spring Security SAML this way:
#SpringBootApplication
#EnableSAMLSSO
public class SpringBootSecuritySAMLDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootSecuritySAMLDemoApplication.class, args);
}
#Configuration
public static class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
}
#Configuration
public static class MyServiceProviderConfig extends ServiceProviderConfigurerAdapter {
#Override
public void configure(ServiceProviderSecurityBuilder serviceProvider) throws Exception {
serviceProvider
.metadataGenerator()
.entityId("localhost-demo")
.and()
.sso()
.defaultSuccessURL("/home")
.idpSelectionPageURL("/idpselection")
.and()
.logout()
.defaultTargetURL("/")
.and()
.metadataManager()
.metadataLocations("classpath:/idp-ssocircle.xml")
.refreshCheckInterval(0)
.and()
.extendedMetadata()
.idpDiscoveryEnabled(true)
.and()
.keyManager()
.privateKeyDERLocation("classpath:/localhost.key.der")
.publicKeyPEMLocation("classpath:/localhost.cert");
}
}
}
There are a couple Demo apps integrated with SSO Circle

Categories