How to add ComponentScan.Filter in #EnableEntityDefinedRegion - gemfire

When I added an includeFilter to #EnableEntityDefinedRegion, it still scanned the whole entity package and created all Region beans. How do I scan the specific Region class? For example, only "Address" Region.
package org.test.entity
#Getter
#Setter
#Region("Address")
public class GfAddress implements Serializable
package org.test.entity
#Getter
#Setter
#Region("CreditCard")
public class GfCreditCard implements Serializable
package org.test.package
public interface IAddressRepository extends GemfireRepository<GfAddress, String>
package org.test.package
public interface ICreditCardRepository extends GemfireRepository<GfCreditCard , String>
#Service
#ClientCacheApplication
#EnableGemfireRepositories(basePackages = IAddressRepository.class, includeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes=AddressRepository.class))
#EnableEntityDefinedRegion(basePackages = GfAddress.class, includeFilters = #ComponentScan.Filter(type = FilterType.REGEX, pattern="GfAddress*"))
public class AddressDataAccess
When I print all the beans that are loaded, I found out that the following beans are created.
Address
CreditCard
IAddressRepository
AddressDataAccess
Version
GemFire : 9.8.6
spring-data-gemfire : 2.1.0
Spring Boot : 2.1.0

Sorry for the delay.
First, have a look at the SDG JIRA ticket I filed, DATAGEODE-352 - "EnableEntityDefinedRegions.includeFilters are inappropriately overridden by framework provided include filters".
In this ticket, I describe a couple of workarounds to this bug (!) in the comments, starting here.
I'd also be careful about your REGEX. I am no Regular Expression expert, but I am certain "GfAddress*" will not properly match the application entity type you are searching for and trying to match even when you pick up the new SDG bits resolving the issue I filed.
I created a similar test, using REGEX, to verify the resolution of the issue, here. This is the REGEX I specified. Using "Programmer*" did not work, as I suspected! That is because the REGEX is not valid and does not match the FQCN as used in the Spring RegexPatternTypeFilter.
Technically, it would be better to be a bit more specific about your type matching and use a "ASSIGNABLE_TYPE" TypeFilter instead, as this test demonstrates.
Finally, while SDG 2.1.x is compatible with GemFire 9.8.x, SD[G] Lovelace, or 2.1.x (e.g. 2.1.18.RELEASE), is officially based on, and only "supports", VMware GemFire 9.5.x (currently 9.5.4).
SDG 2.2.x is officially based on, and "supports", VMware GemFire 9.8.x (currently at 9.8.8).
You can review the new SDG Version Compatibility Matrix for more details.
If you have more questions, please follow up here or in DATAGEODE-352.

Related

bytebuddy apply advice to interface methods - specifically spring data jpa

I am trying to LOG all methods that are invoked in my Springboot application using byte-buddy based java agent.
I am able to log all layers except Spring data JPA repositories, which are actually interfaces. Below is agent initialization:
new AgentBuilder.Default()
.type(ElementMatchers.hasSuperType(nameContains("com.soka.tracker.repository").and(ElementMatchers.isInterface())))
.transform(new AgentBuilder.Transformer.ForAdvice()
.include(TestAgent.class.getClassLoader())
.advice(ElementMatchers.any(), "com.testaware.MyAdvice"))
.installOn(instrumentation);
any hints or workaround that I can use to log when my repository methods are invoked. Below is a sample repository in question:
package com.soka.tracker.repository;
.....
#Repository
public interface GeocodeRepository extends JpaRepository<Geocodes, Integer> {
Optional<Geocodes> findByaddress(String currAddress);
}
Modified agent:
new AgentBuilder.Default()
.ignore(new AgentBuilder.RawMatcher.ForElementMatchers(any(), isBootstrapClassLoader().or(isExtensionClassLoader())))
.ignore(new AgentBuilder.RawMatcher.ForElementMatchers(nameStartsWith("net.bytebuddy.")
.and(not(ElementMatchers.nameStartsWith(NamingStrategy.SuffixingRandom.BYTE_BUDDY_RENAME_PACKAGE + ".")))
.or(nameStartsWith("sun.reflect."))))
.type(ElementMatchers.nameContains("soka"))
.transform(new AgentBuilder.Transformer.ForAdvice()
.include(TestAgent.class.getClassLoader())
.advice(any(), "com.testaware.MyAdvice"))
//.with(AgentBuilder.Listener.StreamWriting.toSystemOut())
.with(AgentBuilder.TypeStrategy.Default.REDEFINE)
.installOn(instrumentation);
I see my advice around controller and service layers - JPA repository layer is not getting logged.
By default, Byte Buddy ignores synthetic types in its agent. I assume that Spring's repository classes are marked as such and therefore not processed.
You can set a custom ignore matcher by using the AgentBuilder DSL. By default, the following ignore matcher is set to ignore system classes and Byte Buddy's own types:
new RawMatcher.Disjunction(
new RawMatcher.ForElementMatchers(any(), isBootstrapClassLoader().or(isExtensionClassLoader())),
new RawMatcher.ForElementMatchers(nameStartsWith("net.bytebuddy.")
.and(not(ElementMatchers.nameStartsWith(NamingStrategy.SuffixingRandom.BYTE_BUDDY_RENAME_PACKAGE + ".")))
.or(nameStartsWith("sun.reflect."))
.<TypeDescription>or(isSynthetic())))
You would probably need to remove the last condition.
for anybody visiting this question / problem - I was able to go around the actual problem with logging actual queries invoked during execution - Bytebuddy is awesome and very powerful - for ex- in my case I am simply advice'ing on my db connection pool classes and gathering all required telemetry -
.or(ElementMatchers.nameContains("com.zaxxer.hikari.pool.HikariProxyConnection"))

Flowable delegateExpression in service task is not working

The flowable version which I'm using is 6.4.1.
#Component
public class MyClass implements JavaDelegate {
#Autowired
private MySampleService mySampleService;
#Override
public void execute(DelegateExecution delegateExecution){
sampleService.doSomeTask();
}
}
Here, myClass bean would be created for class MyClass. Hence, in the bpmn, I can use it like flowable:delegateExpression="${myClass}".
But I'm getting error
"unknown property used in expression: ${myClass}"
And without delegateExpression, mySampleService would be null.
Any suggestions?
There are two ways to configure flowable:
Manually - When using ‘regular’ Spring, you also need to register the ProcessEngineFactoryBean. This will take the engineConfiguration and create a SpringExpressionManager (https://github.com/flowable/flowable-engine/blob/master/modules/flowable-spring/src/main/java/org/flowable/spring/SpringExpressionManager.java) that has access to the expression manager.
SpringBoot, provides out of the box configuration. One only need to provide the needed beans, like DataSource, AsyncExecutor, etc. (based on you the scenario) and spring boot will take care of the rest.

Is there transaction support (TransactionalOperator) for Spring Web Flux projects using Spring Data Neo4j?

I tried using TransactionalOperator in the following component:
#Component
class OrganisationHandler(
private val repository: OrganisationRepository,
private val operator: TransactionalOperator
) { ... }
Starting the application results in the following error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 1 of constructor in com.keen.backend.organisation.OrganisationHandler required a bean of type 'org.springframework.transaction.reactive.TransactionalOperator' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'transactionalOperator' in 'TransactionAutoConfiguration' not loaded because #ConditionalOnSingleCandidate (types: org.springframework.transaction.ReactiveTransactionManager; SearchStrategy: all) did not find any beans
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.transaction.reactive.TransactionalOperator' in your configuration.
I used this documentation as reference. I also stumbled upon this blog post from a year ago. It doesn't seem like there's any SDN implementation of AbstractReactiveTransactionManager to use with TransactionalOperator#create(ReactiveTransactionManager). I couldn't find any relevant ticket on the feature either.
Is there a workaround or perhaps a different approach to transactions for SDN in a Web Flux environment?

Error while setting up Spring Data JPA Read-Only Repository

Spring Boot: 1.3.0.RC1
Spring Boot Starter JPA: 1.3.0.RC1
Having an issue with setting up a Spring Data JPA Read Only Repository.
#NoRepositoryBean
public interface ReadOnlyRepository<T, ID extends Serializable> extends Repository<T, ID> {
T findOne(ID id);
Iterable<T> findAll();
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
Using IntelliJ 15 I am getting this compile error:
Error:(16, 83) java: type org.springframework.stereotype.Repository does not take parameters
The error points at this bit of code: Repository<T, ID>
Has something changed within Spring Data JPA? Am I doing something wrong?
Following examples as listed here: Fine-tuning Spring Data repositories
The error points in the right direction. IntelliJ 15 when using ctrl space pulls the Repository Stereotype import org.springframework.stereotype.Repository rather than the correct import org.springframework.data.repository.
If you type quickly and don't notice the wrong import you will receive the error above.

JAX-RS return a Map<String,String>

I want to retrieve a Map from a using JAX-RS (text/xml)
#GET
public Map<String,String> getMap(){
}
but I am getting the error below:
0000001e FlushResultHa E org.apache.wink.server.internal.handlers.FlushResultHandler handleResponse The system could not find a javax.ws.rs.ext.MessageBodyWriter or a DataSourceProvider class for the java.util.HashMap type and application/x-ms-application mediaType. Ensure that a javax.ws.rs.ext.MessageBodyWriter exists in the JAX-RS application for the type and media type specified.
[10:43:52:885 IST 07/02/12] 0000001e RequestProces I org.apache.wink.server.internal.RequestProcessor logException The following error occurred during the invocation of the handlers chain: WebApplicationException (500 - Internal Server Error) with message 'null' while processing GET request sent to http://localhost:9080/jaxrs_module/echo/upload/getSiteNames
The solution I choose is to wrap a Map and use it for the return param.
#XmlRootElement
public class JaxrsMapWrapper {
private Map<String,String> map;
public JaxrsMapWrapper(){
}
public void setMap(Map<String,String> map) {
this.map = map;
}
public Map<String,String> getMap() {
return map;
}
}
and the method signature will go like this
#GET
public JaxrsMapWrapper getMap()
Your problem is that the default serialization strategy (use JAXB) means that you can't serialize that map directly. There are two main ways to deal with this.
Write an XmlAdaptor
There are a number of questions on this on SO but the nicest explanation I've seen so far is on the CXF users mailing list from a few years ago. The one tricky bit (since you don't want an extra wrapper element) is that once you've got yourself a type adaptor, you've got to install it using a package-level annotation (on the right package, which might take some effort to figure out). Those are relatively exotic.
Write a custom MessageBodyWriter
It might well be easier to write your own code to do the serialization. To do this, you implement javax.ws.rs.ext.MessageBodyWriter and tag it with #Provider (assuming that you are using an engine that uses that to manage registration; not all do for complex reasons that don't matter too much here). This will let you produce exactly the document you want from any arbitrary type at a cost of more complexity when writing (but at least you won't be having complex JAXB problems). There are many ways to actually generate XML, with which ones to choose between depending on the data to be serialized
Note that if you were streaming the data out rather than assembling everything in memory, you'd have to implement this interface.
Using CXF 2.4.2, it supports returning Map from the api. I use jackson-jaxrs 1.9.6 for serialization.
#Path("participation")
#Consumes({"application/json"})
#Produces({"application/json"})
public interface SurveyParticipationApi {
#GET
#Path("appParameters")
Map<String,String> getAppParameters();
....
}
With CXF 2.7.x use
WebClient.postCollection(Object collection, Class<T> memberClass, Class<T> responseClass)
,like this in your rest client code.
(Map<String, Region>) client.postCollection(regionCodes, String.class,Map.class);
for other collections use WebClient.postAndGetCollection().