Consuming Properties at Spring Config Client - spring-cloud

Is there way or reference materials on accessing properties exposed in Spring Cloud Config server at client? I know using #Value, I can get value for one element.
Is it possible to extend or write a framework which can act as layer to consume all such properties and works as bridge to connecting applications.

Using below Annotations and Configurations
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "your.properties.")
#RestController
public class YourController{
private <dataType> <variableName>
/* Dont forget to generate setters and getters as this is bean */
}
Found solution #spencergibb link and other SO links

Related

How to override main application.yml with testing application.yml when testing REST API in an Autowired service class?

I'm writing automated test using TestNG for the REST API of my application. The application has a RestController which contains an #Autowired service class. When the REST endpoint is called with a HTTP GET request, the service looks into a storage directory for XML files, transforms their contents into objects and stores them in a database. The important thing for my question is that the path to the storage directory is stored in /src/main/resources/application.yml (source.storage) and imported via a #Value annotation.
Now, I have the source.storage property also in src/test/resources/application.yml pointing to a different directory within src/test, where I store my testing XML files, and import them to my test class with a #Value annotation again. My test calls the REST endpoint with a HTTP GET. However, it seems that the service still draws the source.storage property the main application.yml, while I would like that value overriden by the one in test application.yml file. In other words, the service tries to import XML files from the application storage directory, rather than from my testing storage.
#ActiveProfiles and #TestPropertySource do not seem to work for me. Scanning the main application.yml for its storage property is not an option, as in the end the application.yml will be drawn from a Spring Cloud Config, and I would not know where the main application.yml would be located.
Is there a way with which I could make the #Autowired service draw the source.storage property from the test application.yml, rather from the main one?
Any advice would be appreciated.
Thanks, Petr
Well, it really depends on what you're trying to build, if it is some sort of unit test of the controller or more likely an integration test. Both approaches are explained in this tutorial.
If you're trying to write integration test, which seems a bit more likely from your question, then #ActiveProfiles or #TestPropertySource should work for you. I would suggest to use profiles, in growing application with a lot of properties it is a bit more convenient to just replace some of the properties for the testing. Below is setup which worked for me when writing integration tests for controller endpoints:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class AreaControllerTest {
#Autowired
TestRestTemplate rest;
#MockBean
private JobExecutor jobExecutor;
#Test
public void test01_List() {
//
}
#Test
public void test02_Get() {
//
}
// ...
}
There are several important things.
The testing properties are in src/test/resources/application-test.properties and merges with the ones in application.properties as the #ActiveProfiles("test") annotation suggests.
Essential is also #RunWith(SpringRunner.class) which is JUnit specific, for TestNG alternative please refer to this SO question.
Finally the #SpringBootTest annotation will start the whole application context.
#FixMethodOrder and #DirtiesContext are further setup of the testing case and are not really necessary.
Notice also the #MockBean annotation, in this case we did not wanted to use real-life implementation of JobExecutor, so we replaced it with mock.
If you want to write unit test where you want to just check the logic of controller and service on their own, then you have to have two test classes, each testing respective classes. Testing service should be standard unit test, testing controller is a bit trickier and is probably more inclined to partial integration test. If this is your case I would recommend to use MockMvc approach explained in the above mentioned tutorial. Small snippet from there:
#RunWith(SpringRunner.class)
#WebMvcTest(GreetingController.class)
public class WebMockTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private GreetingService service;
#Test
public void greetingShouldReturnMessageFromService() throws Exception {
when(service.greet()).thenReturn("Hello Mock");
this.mockMvc.perform(get("/greeting")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello Mock")));
}
}
Notice the #MockBean annotation which mocks service where you can specify your own behaviour of mock. This point is critical, because this sort of test does not load whole application context, but only MVC context, so the services are not available. Again as in the integration test the #RunWith(SpringRunner.class) annotation is essential. Finally #WebMvcTest(GreetingController.class) starts only MVC context of the GreetingController class and not the whole application.
You can try supplying the property directly to the spring boot test.
#SpringBootTest(properties= {"source.storage=someValue"})
Regarding the application picking up the wrong property source, You should also check if your application is being built properly.

Spring data inject repository without explicit type

I have a service that needs to use Neo4jRepository (regular repository provider by spring data).
public class SomeServiceBean<T>{
#Autowired
private Neo4jRepository<T,Long> Neo4jRepository;
}
This class will generate en error:
expected single matching bean but found 2: systemUserRepository,systemClaimRepository
The problem is that systemClaimRepository and systemUserRepository is extending Neo4jRepository<T,Long> as a bean without implementation.
Spring see systemClaimRepository and systemUserRepository as Neo4jRepository<T,Long> because they are extending it.
Is there anyway to inject Neo4jRepository<T,Long>?
Thanks
No how should this work?
You have two beans that match the interface and Spring does not know which implementation to inject.

Inject SecurityContext (similar as SecurityContextHolder from Spring)

I am using Jersey 2.27 on Google App Engine so I am also using the Objectify library which manages my entity classes. I want to be able to get the SecurityContext in one of those classes but Injecting it does not work since the POJO is not managed by Jersey itself.
Is their a way similar to Spring's way via SecurityContextHolder in Jersey 2.27?
#Entity
public class Item {
...
private String modifiedBy;
...
#OnSave
private void onSave() {
this.modifiedBy = SecurityContextHolder.getContext().getUserPrincipal();
}
}

spring data solr showcase

I am trying to understand the spring data solr showcase project.
https://github.com/christophstrobl/spring-data-solr-showcase
After spending quite a bit of time, I could not find how the productRepository is implemented and injected in https://github.com/christophstrobl/spring-data-solr-showcase/blob/master/src/main/java/org/springframework/data/solr/showcase/product/ProductServiceImpl.java
#Service class ProductServiceImpl implements ProductService {
private static final Pattern IGNORED_CHARS_PATTERN = Pattern.compile("\\p{Punct}");
private ProductRepository productRepository;
#Autowired
public void setProductRepository(ProductRepository productRepository) {
this.productRepository = productRepository;
}
The ProductRepository is defined as interface (https://github.com/christophstrobl/spring-data-solr-showcase/blob/master/src/main/java/org/springframework/data/solr/showcase/product/ProductRepository.java) and I did not find any code implementing this interface
interface ProductRepository extends SolrCrudRepository<Product, String> {
#Highlight(prefix = "<b>", postfix = "</b>")
#Query(fields = { SearchableProductDefinition.ID_FIELD_NAME,
SearchableProductDefinition.NAME_FIELD_NAME,
SearchableProductDefinition.PRICE_FIELD_NAME,
SearchableProductDefinition.FEATURES_FIELD_NAME,
SearchableProductDefinition.AVAILABLE_FIELD_NAME },
defaultOperator = Operator.AND)
HighlightPage<Product> findByNameIn(Collection<String> names, Pageable page);
#Facet(fields = { SearchableProductDefinition.NAME_FIELD_NAME })
FacetPage<Product> findByNameStartsWith(Collection<String> nameFragments, Pageable pagebale);
}
Below is how the spring context is configured:
https://github.com/christophstrobl/spring-data-solr-showcase/blob/master/src/main/java/org/springframework/data/solr/showcase/Application.java
If anyone could point me to the direction where this interface is implemented and injected, that would be great.
The showcase makes use of Spring Data repository abstractions using query derivation from method name. So the infrastructure provided by Spring Data and the Solr module take care of creating the required implementations for you. Please have a look at the Reference Documentation for a more detailed explanation.
The showcase itself is built in a way that allows you to step through several stages of development by having a look at the diffs transitioning from one step to the other. So having a look at Step 2 shows how to make use of Custom Repository Implementation, while Step 4 demonstractes how to enable Highlighting using #Highlight.
The goal of Spring Data is to reduce the amount of boilerplate coding (means to reduce repetition of code).
For the basic methods like save,find the implementation will provide by spring and spring will create beans(Objetcs) for these interfaces. To tell the spring that these are my repositories inside this package, we are writing #EnableJpaRepositories(basePackeges="com.spring.repositories") or <jpa:repositories base-package="com.acme.repositories"/> for JPA repositories
Foring solr repositores we have to write #EnableSolrRepositories(basePackages="com.spring.repositories" or <solr:repositories base-package="com.acme.repositories" /> Spring will create objetcs for these interfaces, we can inject these interface objetcs using #Autowire annotation.
Example:
#Service
Pulic class SomeService{
#Autowire
private SampleRepository;
/* #postConstruct annotation is used to execute method just after creating bean
and injecting all dependencies by spring*/
#PostConstruct
public void postConstruct(){
System.out.println("SampleRepository implementation class name"+ SampleRepository.getClass());
}
}
The above example is to see the implementation class of SampleRepository interface (This class is not user defined, it is class given by spring).
For reference documentation link http://docs.spring.io/spring-data/solr/docs/2.0.2.RELEASE/reference/html/. Try to read this simple documentation you can get more knowlede on spring-data.

Configuration for EJB lookups at runtime

I have several services deployed as EJBs on a JBoss-AS-7.1 server. Many applications use these EJBs by doing a lookup like this:
#EJB(lookup = "java:global/FooService/FooBean!com.xyz.FooBeanRemote")
private FooBeanRemote fooBeanRemote;
The problem is that the lookup string is hard-coded in the source. I want to be able to change this lookup at runtime - without a re-compilation - because FooService may be updated some time in the future, and perhaps have a different implementation. In addition, the ejb could also move to a different server instance.
What would be the best way to achieve this?
Use ejb-jar.xml instead of annotation (check here)
use InitialContext in your code to lookup for bean and move bean name to properties file
Implement CDI producer methods in separate jar
--EDIT---
Quick HOWTO about last point:
1. Create qualifier
#Qualifier
#Retention(RUNTIME)
#Target({FIELD, TYPE, METHOD})
public #interface FooService {
}
2. Create producer method
public class EJBProducer {
#Produces
#FooService
#EJB(lookup = "java:global/FooService/FooBean!com.xyz.FooBeanRemote")
private FooBeanRemote fooBeanRemote;
}
3. Use in your code
#Inject #FooService
private FooBeanRemote fooBeanRemote;
Two first points may be in another jar archive (remember to include there META-INF/beans.xml file). You can also use producer method instead of field, and access ejb programmatically.