Bean definition in spring integration - spring

I am new to spring. I want to write a bean definition for the code below.
package com.abc.common.filter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
public class RegexFilter implements Filter<String> {
Logger logger = Logger.getLogger(RegexFilter.class);
private Pattern regex;
private String lastMatch;
public RegexFilter(String regexString) {
this.lastMatch = null;
regex = Pattern.compile(regexString, Pattern.UNICODE_CHARACTER_CLASS);
}
#Override
public boolean matches(String text) {
text = text.toLowerCase();
if (text == null) {
logger.error("No text set for matching!");
return false;
}
Matcher matcher = regex.matcher(text);
if (matcher.find(0)) {// always start at index 0
this.lastMatch = matcher.group();
if (logger.isDebugEnabled()) {
logger.debug(matcher.group() + " found!");
}
return true;
}
return false;
}
public String getLastMatch(){
return this.lastMatch;
}
}
I am stuck after this line, i dont know how to include index or name? A little more clarification on index and values would be more than helpful.
<bean id="regexfilter" class="com.abc.common.filter.RegexFilter" />
<constructor-arg name="regexString" />
</bean>

You can define your bean
<bean id="regexfilter" class="com.abc.common.filter.RegexFilter" />
<constructor-arg type="java.lang.String" value="valueforregexstring"/>
</bean>
You can see more about bean definitions here
http://www.tutorialspoint.com/spring/constructor_based_dependency_injection.htm

in annotation based manor with pure java you can do something like this:
#Configuration
public class ApplicationConfig {
#Bean
public Filter regexFilter() {
return new RegexFilter("value_for_the_regex_filter");
}
}
or simply:
#Service
public class RegexFilter implements Filter<String> {
...
}

Related

How to add a NameId value to a AttributeValue using OpenSAML2

Using OpenSAML2 how does one create the following XML:
<saml:Attribute Name="urn:mace:dir:attribute-def:eduPersonTargetedID"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue>
<saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">c693b1c47a0da7de6518bc30a1bb8d2e44b56980</saml:NameID>
</saml:AttributeValue>
</saml:Attribute>
Extending OpenSAML fixes the issue as it doesn't seem to support NameID values within Attribute Value elements.
The following files are required to implement the AttributeValue.
Builder
package com.blah;
import org.opensaml.common.impl.AbstractSAMLObjectBuilder;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.core.AttributeValue;
public class AttributeValueBuilder extends AbstractSAMLObjectBuilder<AttributeValue>{
public AttributeValueBuilder() {
}
#Override
public AttributeValue buildObject() {
return buildObject(SAMLConstants.SAML20_NS, AttributeValue.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX);
}
#Override
public AttributeValue buildObject(String namespaceURI, String localName, String namespacePrefix) {
return new AttributeValueImpl(namespaceURI, localName, namespacePrefix);
}
}
Implementation
package com.blah;
import java.util.ArrayList;
import java.util.List;
import org.opensaml.common.impl.AbstractSAMLObject;
import org.opensaml.xml.XMLObject;
public class AttributeValueImpl extends AbstractSAMLObject implements org.opensaml.saml2.core.AttributeValue{
protected AttributeValueImpl(String namespaceURI, String elementLocalName,
String namespacePrefix) {
super(namespaceURI, elementLocalName, namespacePrefix);
}
private List<XMLObject> children = new ArrayList<XMLObject>();
#Override
public List<XMLObject> getOrderedChildren() {
return children;
}
}
Marshaller
package com.blah;
import org.opensaml.common.impl.AbstractSAMLObjectMarshaller;
public class AttributeValueMarshaller extends AbstractSAMLObjectMarshaller {
}
Unmarshaller
package com.blah;
import org.opensaml.common.impl.AbstractSAMLObjectUnmarshaller;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.io.UnmarshallingException;
public class AttributeValueUnmarshaller extends AbstractSAMLObjectUnmarshaller {
#Override
protected void processChildElement(XMLObject parentSAMLObject, XMLObject childSAMLObject)
throws UnmarshallingException {
AttributeValueImpl attributeValue = (AttributeValueImpl) parentSAMLObject;
attributeValue.getOrderedChildren().add(childSAMLObject);
}
}
Once these files are included they need to be added to the OpenSAML bootstrapping configuration file saml2-assertion-config.xml (I copied it from the OpenSAML jar and placed it into the root of the Java src):
<!-- AttributeValue -->
<ObjectProvider qualifiedName="saml2:AttributeValue">
<BuilderClass className="com.blah.AttributeValueBuilder" />
<MarshallingClass className="com.blah.AttributeValueMarshaller" />
<UnmarshallingClass className="com.blah.AttributeValueUnmarshaller" />
</ObjectProvider>
<ObjectProvider qualifiedName="saml2:AttributeValueType">
<BuilderClass className="com.blah.AttributeValueBuilder" />
<MarshallingClass className="com.blah.AttributeValueMarshaller" />
<UnmarshallingClass className="com.blah.AttributeValueUnmarshaller" />
</ObjectProvider>
It is now possible to add any element to the Attribute Value body.
private static XMLObject createAttributeValueNameId(String value) throws ConfigurationException {
XMLObjectBuilder<AttributeValueImpl> attrBuilder = getSamlBuilder().getBuilder(AttributeValue.DEFAULT_ELEMENT_NAME);
AttributeValueImpl attributeValue = attrBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
XMLObjectBuilder<AttributeValue> builder = getSamlBuilder().getBuilder(NameID.DEFAULT_ELEMENT_NAME);
NameID nameId = (NameID) builder.buildObject(NameID.DEFAULT_ELEMENT_NAME);
nameId.setFormat(NameID.UNSPECIFIED);
nameId.setValue(value);
attributeValue.getOrderedChildren().add(nameId);
return attributeValue;
}

Implement interface in runtime Java EE and Spring

I would like to implement the interface at runtime based on variable.
Example :
Class A implements interface1 {
public getValue() {}
}
Class B implements interface1 {
public getValue() {}
}
So I would like to have variable sitting in configuration..., for example ClasstoImplement=A
So, if ClasstoImplement=A, then I need to call Class A.getValue()
If ClasstoImplement=B, then I need to call Class B.getValue() at runtime. And I should be able to change value of ClasstoImplement at runtime.
My application is Spring based and runs in Tomcat.
Can someone please help me to find out if there is any way??
There are many possible solutions. The one of them is to use org.springframework.aop.target.HotSwappableTargetSource.
take a look at implementation that could be considered:
public class CustomSwappable<T> implements Interface1 {
private HotSwappableTargetSource targetSource;
private String key;
private Map<String, T> swappableBeans;
#PostConstruct
private void init() {
targetSource = new HotSwappableTargetSource(swappableBeans.values().iterator().next()); // first is the default
}
// you need to track changes in config and call this method if any modifications were done
public void configChanged(String key, String value) {
if (!this.key.equals(key)) {
return;
}
if (!swappableBeans.containsKey(value)) {
return;
}
targetSource.swap(swappableBeans.get(value));
}
#Override
public String getValue() {
return ((Interface1)targetSource.getTarget()).execute();
}
#Required
public void setConfigurationKey(String key) {
this.key = key;
}
#Required
public void setSwappableBeans(Map<String, T> swappableBeans) {
this.swappableBeans = swappableBeans;
}
}
and bean declaration should as follows:
<bean id="Interface1Swappable" class="path.to.CustomSwappable">
<property name="configurationKey" value="swappableKey"/>
<property name="swappableBeans">
<util:map value-type="path.toInterface1">
<!-- first is default -->
<entry key="classA">
<bean class="path.to.class.A"/>
</entry>
<entry key="classB">
<bean class="path.to.class.B"/>
</entry>
</util:map>
</property>
</bean>

Spring/Hibernate - validating groups manually and return a BindingResult

I want to manually validate (not using #Valid or #Validated) using groups and return a BindingResult.
I have a spring validator configured
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" >
<property name="validationMessageSource" ref="messageSource"/>
</bean>
And this is the class that does the validation, it works but notice that groups is not being used.
#Component
public class ObjectValidatorImpl implements ObjectValidator {
private final Validator validator;
#Autowired
public ObjectValidatorImpl(final Validator validator) {
super();
this.validator = validator;
}
#Override
public final <T> BindingResult getBindingResults(
final T objectToValidate, final Class<?>...groups) {
final DataBinder binder = new DataBinder(objectToValidate);
binder.setValidator(validator);
//ideally, I would like to set the groups on the binder here like
//binder.setGroups(groups);
binder.validate();
return binder.getBindingResult();
}
}
I cant figure out how to get the Validator to use the groups, the seems to be no method for it.
I would like to call it like this.
objectValidator.validate(myObject, Class1.class, Class2.class)
I had a similar issue, and ended up extending the SpringValidatorAdapter class so that I could perform the validation and specify the groups.
ExtendedSpringValidatorAdapter adapter = new ExtendedSpringValidatorAdapter(validator);
adapter.validate(objectToValidate, bindingResult, Class1.class, Class2.class);
Here is the definition of the extended validator:
package com.example.validator;
import org.springframework.beans.NotReadablePropertyException;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.util.Set;
public class ExtendedSpringValidatorAdapter extends SpringValidatorAdapter {
// ========================================================================
// ========================================================================
// ========================================================================
public ExtendedSpringValidatorAdapter(Validator targetValidator) {
super(targetValidator);
}
// ========================================================================
// ========================================================================
// ========================================================================
public void validate(Object target, Errors errors, Class<?>... groups) {
if (groups == null || groups.length == 0 || groups[0] == null) {
groups = new Class<?>[]{Default.class};
}
Set<ConstraintViolation<Object>> result = validate(target, groups);
for (ConstraintViolation<Object> violation : result) {
String field = violation.getPropertyPath().toString();
FieldError fieldError = errors.getFieldError(field);
if (fieldError == null || !fieldError.isBindingFailure()) {
try {
errors.rejectValue(field,
violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName(),
getArgumentsForConstraint(errors.getObjectName(), field, violation.getConstraintDescriptor()),
violation.getMessage());
} catch (NotReadablePropertyException ex) {
throw new IllegalStateException("JSR-303 validated property '" + field +
"' does not have a corresponding accessor for Spring data binding - " +
"check your DataBinder's configuration (bean property versus direct field access)", ex);
}
}
}
}
}
I think the easiest way is to use a SmartValidator. You can inject it just like a regular Validator. By using a SmartValidator you have Validation Hints, which you can use to pass the javax.validation.group as parameters. And the final code can be as simple as this:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.SmartValidator;
#Component
public class FooController {
#Autowired
private SmartValidator validator;
public void validate(MyObject target, Errors errors) {
validator.validate(target, errors, FirstCheck.class, SecondCheck.class);
}
}
Since 3.1 version there are
org.springframework.validation.DataBinder#validate(java.lang.Object...validationHints)
So just do:
binder.validate(Class1.class, Class2.class);
Inside method SmartValidator is used:
if(... validator instanceof SmartValidator) {
((SmartValidator) validator).validate(target, bindingResult, validationHints);

Load-time weaving with AspectJ in the Spring Framework Private methods

I have built an application to test injecting log information (Entering and Exiting) around classes. I have built it using spring and used the following example for building it.
http://static.springsource.org/spring/docs/2.5.5/reference/aop.html#aop-aj-ltw
It works great now but I have 2 issues:
Private methods are not included when the log is weaved around the method. Is there a setting in the xml settings for spring to allow private methods to be weaved or is there another way around this?
I have to include all packages that are to be weaved in the META-INF/aop.xml for this to be able to work. Is there a setting to be used so that the log information can be weaved for all classes created in the project without having to add the package name to the aop.xml.
Below I have included all code and xml that is used. As I said all is working fine except the 2 issues above. Please assist me.
app.java
package se.jpab.application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;
#Service
public class App
{
public static void main( String[] args )
{
ApplicationContext appContext = new ClassPathXmlApplicationContext( new String[] { "spring.xml" });
Client client = (Client) appContext.getBean("client");
Location clientLocation = (Location) appContext.getBean("location");
// Set all values
clientLocation.setAdress1("Adress 1");
clientLocation.setAdress2("Adress 2");
clientLocation.setBox("N/A");
clientLocation.setCity("City of Dallas");
client.setName("John Doe");
client.setUrl("http://www.url.com");
client.setLocation(clientLocation);
// Print out all values
System.out.println(client.getName());
System.out.println(client.getUrl());
System.out.println(client.getLocation().getAdress1());
System.out.println(client.getLocation().getAdress2() + " " + client.getLocation().getCity());
}
}
Client.java
package se.jpab.application;
import org.springframework.stereotype.Service;
#Service
public class Client {
String name;
String url;
Location location;
//Constructors
public Client(String custName, String custUrl, Location custLocation){
name = custName;
url = custUrl;
location = custLocation;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public Client(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
printThis(name);
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public void printThis(String inStr) {
System.out.println("PRIVAT METOD");
System.out.println("Inkommand sträng --> " + inStr);
}
}
Location.java
package se.jpab.application;
import org.springframework.stereotype.Service;
#Service
public class Location {
String city;
String adress1;
String adress2;
String box;
//Constructors
public Location (String city, String adress1, String adress2, String box){
this.city = city;
this.adress1 = adress1;
this.adress2 = adress2;
this.box = box;
}
public Location (){
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAdress1() {
return adress1;
}
public void setAdress1(String adress1) {
this.adress1 = adress1;
}
public String getAdress2() {
return adress2;
}
public void setAdress2(String adress2) {
this.adress2 = adress2;
}
public String getBox() {
return box;
}
public void setBox(String box) {
this.box = box;
}
}
aop.xml
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options=" -showWeaveInfo">
<!-- only weave classes in our application-specific packages -->
<include within="se.jpab.application.*"/>
<include within="se.jpab.aspect.*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="se.jpab.aspect.InjectLogg"/>
</aspects>
</aspectj>
Aspect
package se.jpab.aspect;
import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class InjectLogg {
private static final Log fallbackLogger = LogFactory.getLog(InjectLogg.class);
#Around("execution(public * se.jpab.application..*.*(..))")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
Object invoker = pjp.getThis();
Log logger;
logger = LogFactory.getLog(getClassNameFrom(invoker.getClass()));
// Start injecting logg messages on entering a method.
logger.info("ENTERING: (" + pjp.getSignature().getName() + ")");
try {
logger.info("ARGUMENTS: " + Arrays.toString(pjp.getArgs()) + ")");
} catch (NullPointerException e) {
logger.info("ARGUMENTS: No arguments");
}
try {
// proceed to original method call
Object result = pjp.proceed();
// Injecting exiting messages after method is finished
logger.info("RESULT: " + result);
logger.info("EXITING: (" + pjp.getSignature().getName() + ")");
// Return the result of the method we are logging
return result;
} catch (IllegalArgumentException e) {
// same with ThrowsAdvice
logger.info("Exception. Throws IllegalArgumentException");
throw e;
}
}
private String getClassNameFrom(Class invokerClassName) {
// Function that ....... To be continued JP
// Add check for that string contains $$ and se.goteborg if not then
// return fallback logger class.
String[] classNameParts = invokerClassName.getName().split("$$");
int positionOfPackageName = classNameParts[0].indexOf("se.jpab");
String className = classNameParts[0].substring(positionOfPackageName);
return className;
}
}
Spring configuration (spring.xml)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:load-time-weaver/>
<context:annotation-config />
<context:component-scan base-package="se.jpab"/>
</beans>
Your first question:
Private methods are not included when the log is weaved around the
method. Is there a setting in the xml settings for spring to allow
private methods to be weaved or is there another way around this?
If you want to weave private methods, use full AspectJ and therein a privileged aspect, not Spring AOP. The Spring manual says:
If your interception needs include protected/private methods or even
constructors, consider the use of Spring-driven native AspectJ weaving
instead of Spring's proxy-based AOP framework. This constitutes a
different mode of AOP usage with different characteristics, so be sure
to make yourself familiar with weaving first before making a decision.
Your second question:
I have to include all packages that are to be weaved in the
META-INF/aop.xml for this to be able to work. Is there a setting to be
used so that the log information can be weaved for all classes created
in the project without having to add the package name to the aop.xml.
You can catch a package an all its subpackages with the .. syntax, e.g. se.jpab.application..* or even se.jpab..*. You can also combine several conditions with boolean operators. See the AspectJ documentation for examples.

How should I use #CachePut and #CacheEvict annotations with ehCache (ehCache 2.4.4, Spring 3.1.1)

I tried some new Spring features and I found out that #CachePut and #CacheEvict annotations has no effect. May be I do something wrong. Could you help me?
My applicationContext.xml.
<cache:annotation-driven />
<!--also tried this-->
<!--<ehcache:annotation-driven />-->
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cache-manager-ref="ehcache"/>
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:ehcache.xml"/>
This part works well.
#Cacheable(value = "finders")
public Finder getFinder(String code)
{
return getFinderFromDB(code);
}
#CacheEvict(value = "finders", allEntries = true)
public void clearCache()
{
}
But if I want remove single value from cache or override it I can't do that. What I tested:
#CacheEvict(value = "finders", key = "#finder.code")
public boolean updateFinder(Finder finder, boolean nullValuesAllowed)
{
// ...
}
/////////////
#CacheEvict(value = "finders")
public void clearCache(String code)
{
}
/////////////
#CachePut(value = "finders", key = "#finder.code")
public Finder updateFinder(Finder finder, boolean nullValuesAllowed)
{
// gets newFinder that is different
return newFinder;
}
I found the reason why it didn't work. I called this methods from other method in the same class. So this calls didn't get through Proxy object therefore the annotations didn't work.
Correct example:
#Service
#Transactional
public class MyClass {
#CachePut(value = "finders", key = "#finder.code")
public Finder updateFinder(Finder finder, boolean nullValuesAllowed)
{
// gets newFinder
return newFinder;
}
}
and
#Component
public class SomeOtherClass {
#Autowired
private MyClass myClass;
public void updateFinderTest() {
Finder finderWithNewName = new Finder();
finderWithNewName.setCode("abc");
finderWithNewName.setName("123");
myClass.updateFinder(finderWithNewName, false);
}
}

Resources