Spring Boot Starter Data Rest change URL of repository from the root URI - rest

Following the spring.io example here: http://spring.io/guides/gs/accessing-data-rest/ for exposing a repository as a rest web service works just fine, but I cannot see how to change the URL of the exposed service. The API documentation is a little vague as to what the annotation parameters mean, perhaps some prior knowledge is assumed.
What I want - A HATEOAS service accessed at http://localhost:8080/api/people for a People repository. I want to achieve this URL using annotations only, not messing with the context root or similar. I tried the following repository annotations:
#RepositoryRestResource(collectionResourceRel = "api/people", path = "people")
#RepositoryRestResource(collectionResourceRel = "people", path = "api/people")
#RepositoryRestResource(collectionResourceRel = "api/people", path = "api/people")
None of these work.
I know I have probably missed the obvious, much appreciate anyone who can point it out.

As of Spring Boot 1.2 you are able to set this property:
spring.data.rest.baseUri=api
Alternatively:
spring.data.rest.base-uri=api
(Spring Boot uses a relaxed binding system)
NOTE: I have found that if you have extended RepositoryRestMvcConfiguration with custom configuration, the property does not take effect. For more information see:
https://github.com/spring-projects/spring-boot/issues/2392
Once the next version of Spring Boot is released (after 1.2.1), the solution will be to extend RepositoryRestMvcBootConfiguration instead.

As of Spring Boot 1.4.3 the code should be :
spring.data.rest.base-path:api
(I think baseUri is deprecated since 1.2.3)

Although I couldn't change the base path of the REST services using the annotation #RepositoryRestResource combined with a CrudRepository, I managed to do it using a JpaRepository and a custom controller with the annotation #RequestMapping.
The repository could be something like:
#Repository
interface PersonRepository : JpaRepository<Person, Long>
And the controller:
#RestController
#RequestMapping("/api/people")
class PersonRestController(private val personRepository: PersonRepository) {
...
On the other hand, you can change the base path of all your REST services modifying it in the application.properties file of your project. Add the lines:
# DATA REST (RepositoryRestConfiguration)
spring.data.rest.base-path = api
Change api with the path you wish you use in your URLs. The first line is a comment and, as so, it's not mandatory, but is useful to mark the nature of the configuration value for future references.
You can find all the common application properties of Spring Boot 2.0.1 in the Appendix A of the documentation.

Related

Hazelcast reactive support for WriteThrough in Hazelcast 4.2

We wanted to implement WriteThrough/write behind in Hazelcast using MapStore for Postgres DataStore using ReactiveClient. But could not succeed and we are also not getting any sample for reactive approach.
We are implementing MapStore Interface to achieve WriteThrough Caching Pattern.
we have to inject the Respository in Mapstore and we are trying inject using #Autowired Annotation.
But we are not able to do, we are getting error repository as null.
Can we get some working example for Hazelcast 4.2 with Postgress as Datastore in reactive way?
Thanks
Jeni Ambrose
We tried with Autowiring the Repositories in Mapstore implementation
Here's one way:
#Bean
public Config config(AccountRepository accountRepository) {
Config config = new ClasspathYamlConfig("hazelcast.yml");
MapStoreConfig accountMapStoreConfig = new MapStoreConfig();
accountMapStoreConfig.setInitialLoadMode(MapStoreConfig.InitialLoadMode.EAGER);
accountMapStoreConfig.setEnabled(true);
accountMapStoreConfig.setImplementation(new AccountMapLoader(accountRepository));
MapConfig accountMapConfig = new MapConfig();
accountMapConfig.setName("account");
accountMapConfig.setMapStoreConfig(accountMapStoreConfig);
config.getMapConfigs().put(accountMapConfig.getName(), accountMapConfig);
return config;
}
You can have most (or none!) of the config in a static file, load it, and amend it to add Spring managed bits.
Also, 4.2 is old, use 5.2.1 or whatever is newest when you get to doing this.

Apache Camel REST - not connecting

I'm trying to get Apache Camel's REST DSL working but it's not connecting for me.
I've got a RouteBuilder that's being called:
#Override
public void configure() {
restConfiguration().component("servlet")
.contextPath("/")
.enableCORS(true)
.dataFormatProperty("prettyPrint", "true")
.apiContextPath("/api-doc")
.apiProperty("api.version", buildVersion)
.apiProperty("cors", "true")
.bindingMode(RestBindingMode.json);
rest("/say/hello")
.get().route().transform().constant("Hello World");
}
but then the routes don't actually work.
This is inside a Spring Boot app that has other REST endpoints defined via JAX-RS but this is an integration package that I want to be able to keep separate. The weird thing is that this WAS working a few months ago before I had to work on other things, but now, coming back to it, I can't even get this simple endpoint working.
I've got Camel in my Maven pom.xml and everything seems to be starting correctly, but nothing happens when I hit http:://localhost:9071/say/hello, I just get the standard Tomcat 404 page.
Any thoughts on what I'm missing?
According to this: http://www.baeldung.com/apache-camel-spring-boot
As of Camel’s version 2.19, this configuration has been dropped as the
CamelServlet is by default set to “/camel”.
so /camel/say/hello is the correct URL and it works for me. Still looking at how to customize this.
EDIT:
Here's how to customize this under Spring Boot. You add a property to application.properties like this:
camel.component.servlet.mapping.contextPath=/*

Spring cloud config properties not honouring config properties

I wish to use consul strictly as a config source.
I am using spring-cloud-consul-config to get my config.
I am using git2consul to load files into consul and read them.
As per the spring cloud documentation I have added the following to my build.gradle
compile ("org.springframework.cloud:spring-cloud-starter-consul-config")
and have the following in my application.properties
spring.application.name=test-service
spring.cloud.consul.config.enabled=true
spring.cloud.consul.enabled=true
spring.cloud.consul.config.format=FILES
The problem I am facing is that the expected properties are not being loaded into the ConfigurationProperties beans. On further debugging in the ConsulPropertySourceLocator::locate(Environment environment) method, I see that the this.properties object is still loaded with KEY_VALUE enum.
This led me to ConsulConfigBootstrapConfiguration class, where the ConsulConfigProperties bean is being instantiated using a constructor.
Is this the problem or do I have something wrong in my setup.
If someone has a working setup of git2consul and spring cloud config, please can you point me to it for reference.
These values that you have in application.properties
spring.application.name=test-service
spring.cloud.consul.config.enabled=true
spring.cloud.consul.enabled=true
spring.cloud.consul.config.format=FILES
need to be in bootstrap.properties.

WildFly management - list/detect REST endpoints deployed in WildFly

Is there a way (e.g. from a WildFly management console) to list all REST endpoints deployed in WildFly? Or to list them in a log while a server is starting?
Using the RegistryStatsResource
With RESTEasy (that is shipped with WildFly), you could add the following to your web.xml:
<context-param>
<param-name>resteasy.resources</param-name>
<param-value>org.jboss.resteasy.plugins.stats.RegistryStatsResource</param-value>
</context-param>
And then request the following URL:
http://[hostname]:[port]/[context]/[api-path]/resteasy/registry
Such endpoint can produce XML and JSON content. Just add the Accept header to the request with the desired media type:
application/xml
application/json
Checking the source code
If you are interested in the source code to create your own implementation, have a look at the RegistryStatsResource class on GitHub.
The most relevant part of the source code is shown below (it's RESTEasy specific):
ResourceMethodRegistry registry = (ResourceMethodRegistry)
ResteasyProviderFactory.getContextData(Registry.class);
for (String key : registry.getBounded().keySet()){
List<ResourceInvoker> invokers = registry.getBounded().get(key);
for (ResourceInvoker invoker : invokers) {
if (invoker instanceof ResourceMethodInvoker) {
ResourceMethodInvoker rm = (ResourceMethodInvoker) invoker;
// Extract metadata from the ResourceMethodInvoker
}
}
Swagger may be an alternative
Depending on your requirements, you can use Swagger to document your API. It comes with a set of annotations to describe your REST endpoints.
Then use Swagger UI to provide a live documentation for your API.
Note: As of February 2017, looks like the RegistryStatsResource class is completely undocumented. I occasionally discovered it when digging into the RESTEasy source code for debugging purposes. Also, I found this JBoss EAP issue that tracks the lack of documentation for that class.
From the Management Console, you can view the published endpoints.
When you login as an administrator, Click the Runtime option on the top navigation bar as shown below.
Click the JAX-RS option, then click the REST Resources option. This will display the endpoints to the far right.

Upgrading from DeploymentService to ProfileService in JBoss 5.1.0 GA

In Jboss 5.1 the Profile Service does what the Deployment Service was doing in Jboss 4.x.In Jboss 4.x I was using the Deployment Service to create a datasource "on-the-fly" and I was wondering if I could do the same thing using the Profile Service (since Deployment Service doesn't exist any more in Jboss 5.x).
Does anyone know a practical guid on using ProfileService?
Thank you ,
Regards.
I don't know of any guide but I can provide you with my experience using the Profile Service and a few links to JBoss wiki pages on this topic. I'd like to post more links but the spam protection doesn't allow me to post more than two, but you should easily find the other pages in the wiki on the ProfileService. Don't be suprised in case you don't find much, there isn't more.
ProfileService ManagementView
http://community.jboss.org/wiki/ProfileServiceManagementView
ProfileService DeploymentTemplates
http://community.jboss.org/wiki/ProfileServiceDeploymentTemplates
There you'll find usefull information about the ProfileService but no detailed information is available in the jboss wiki as far as I can tell.
In order to create Datasources on the fly you can use the DeploymentTemplates (also for creating message queues and topics) The last link provides you with information on how to use the templates but not with all the template names and their properties. You can list them programatically though.
// Get all Templates
for(String template : mgtView.getTemplateNames())
{
System.out.println("=========================================");
System.out.println("Listing properties for template: "+template);
DeploymentTemplateInfo info = mgtView.getTemplate(template);
for(String prop : info.getProperties().keySet())
System.out.println("- "+prop);
}
In order to get the ManagementView (mgtView) from an external java programm you can use something similiar to this:
// set security policy
System.setProperty("java.security.policy", "<path_to_policy_file>");
System.setSecurityManager( new RMISecurityManager() ) ;
// set initial context properties
Hashtable<String, String> env = new Hashtable<String, String>();
env.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
env.put("java.naming.provider.url","jnp://localhost:1099");
env.put("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
ctx = new InitialContext(env);
// login to JBoss
SecurityClient client = SecurityClientFactory.getSecurityClient();
client.setSimple("admin", "admin");
client.login();
// get ProfileService and ViewManager
ProfileService ps = (ProfileService) ctx.lookup("ProfileService");
mgtView = ps.getViewManager();
What you want to get is the Java Naming Conext (InitialContext). In order to do that you'll need a security policy (you can use the java.policy file which is located in JBOSS_HOME/server/SERVER_DIR/conf/),security manager and environment properties to get the context. The java.naming.provider.url specifies the location of the JBoss naming service (default port is 1099).
Usually you would have to authenticate at this point which is done with the SecurityClient.
Finally you can use the context to grap the ProfileService.
At this point most of the anoying stuff is done und you can start playing around.
getViewManager() returns the ViewManager with which you can create datasources on the fly and getDeploymentManager() will give you the DeploymentManager with which you can deploy, undeploy, start, stop applications and other deployments.
The libraries you'll need to do that are located in
JBOSS_HOME/client
JBOSS_HOME/lib
JBOSS_HOME/common/lib
I've read several times that including the jbossall-client.jar in the client directory should be enough but that's actually not true. You need libraries from all three directories as far as I can tell (couldn't do it without referencing all of them at least). I haven't figured out which exact jars you need though...
IMPORTANT: The ProfileService in Jboss 5 Community Edition has some bugs though which got fixed in JBoss 6. I'd either suggest using a newer JBoss version or the Enterprise Edition.