How to inject bean in a Tapestry service - spring

I want to inject bean in a Tapestry service (not in a page).
For the moment, I use this :
public class EntityRealm extends AuthorizingRealm {
ApplicationContext ctx = new ClassPathXmlApplicationContext("/application-context-security.xml");
SecurityServices securityServices = (SecurityServices)ctx.getBean("securityServices");
It works, but I want use this :
public class EntityRealm extends AuthorizingRealm {
#Inject
private SecurityServices securityServices;
And my applicationContext is in the web.xml.
In this second case, the injection doesn't work. Why ?
AppModule.java :
public class AppModule
{
//#Resource(name = "realm")
#Inject
private static EntityRealm realm;
#Contribute(WebSecurityManager.class)
public static void addRealms(Configuration<EntityRealm> configuration) {
//EntityRealm realm = new EntityRealm();
configuration.add(realm);
}
public static void contributeFactoryDefaults( MappedConfiguration<String, Object> configuration)
{
configuration.override(SecuritySymbols.LOGIN_URL, "/login");
configuration.override(SecuritySymbols.UNAUTHORIZED_URL, "/login");
configuration.override(SecuritySymbols.SUCCESS_URL, "/index");
configuration.override(SymbolConstants.APPLICATION_VERSION, "2.0-SNAPSHOT");
}
public static void contributeApplicationDefaults(MappedConfiguration<String, Object> configuration)
{
configuration.add(SymbolConstants.HMAC_PASSPHRASE, new BigInteger(130, new SecureRandom()).toString(32));
configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en,fr");
configuration.add( "tapestry.default-cookie-max-age", "31536000" );
}
public RequestFilter buildTimingFilter(final Logger log)
{
return new RequestFilter()
{
public boolean service(Request request, Response response, RequestHandler handler)
throws IOException
{
long startTime = System.currentTimeMillis();
try
{
return handler.service(request, response);
} finally
{
long elapsed = System.currentTimeMillis() - startTime;
log.info(String.format("Request time: %d ms", elapsed));
}
}
};
}
public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
#Local
RequestFilter filter)
{
configuration.add("Timing", filter);
}
}
And the EntityRealm.java :
public class EntityRealm extends AuthorizingRealm {
//***************************************
//************* Attributes *************
//***************************************
//ApplicationContext ctx = new ClassPathXmlApplicationContext("/application-context-security.xml");
//SecurityServices securityServices = (SecurityServices)ctx.getBean("securityServices");
//#Resource(name = "securityServices")
#Inject
private SecurityServices securityServices;
//***************************************
//************ Constructors *************
//***************************************
public EntityRealm() {
super(new MemoryConstrainedCacheManager());
setName("myapprealm");
setAuthenticationTokenClass(UsernamePasswordToken.class);
}
//***************************************
//********** Public Methods *************
//***************************************
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
if (principals == null) throw new AuthorizationException("PrincipalCollection was null, which should not happen");
application-context.xml :
<bean id="realm" class="net.atos.m2m.telecom.ihm.services.EntityRealm">
<property name="securityServices" ref="securityServices"></property>
</bean>
<bean id="securityServices" class="net.atos.m2m.telecom.ihm.applicatif.services.security.impl.SecurityServicesImpl">
<property name="servicesTelSecu" ref="servicesTelSecu"></property>
<property name="converterSecDSPtoDTO" ref="converterSecDSPtoDTO"></property>
<property name="converterSecDTOtoDSP" ref="converterSecDTOtoDSP"></property>
</bean>
Can you help me ?
Thank you.

How i say in previous comment, if you create EntityRealm in this way .. new EntityRealm() the inject\autowire does not work.
You must define EntityRealm as bean .. XML or Annotation.
<bean id="entityRealm" class="package.EntityRealm"/>
<bean id="securityServices" class="package.SecurityServices"/>

You can use #Resource instead,
#Resource(name = "securityServices")
private SecurityServices securityServices;
And make sure that application-context-security.xml file is loaded by Spring.

Related

configured as a single instance, but instantiated twice

spring.version=5.2.7.RELEASE
public class Service15 {
public Service15(){
System.out.println("service15 init");
}
}
public class Service15Factory implements FactoryBean, BeanFactoryAware {
private BeanFactory beanFactory;
public Service15Factory(){
System.out.println("serviceFactory15 init");
}
#Override
public Object getObject() throws Exception {
beanFactory.getBean("service16");
return new Service15();
}
#Override
public Class<?> getObjectType() {
return Service15.class;
}
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
public class Service16 {
private Service15 service15;
public Service16(){
System.out.println("service16 init");
}
public void setService15(Service15 service15){
this.service15 = service15;
}
}
configuration:
<bean id="service15" class="com.myspring.service.Service15Factory" scope="singleton">
</bean>
<bean id="service16" class="com.myspring.service.Service16">
<property name="service15" ref="service15"></property>
</bean>
I created three classes,service15 will be created by getObject of Service15Factory, and Service16 dependent on service15,service15 will be Initialized twice

How do i inject a spring bean into a hibernate SequenceGenerator

I have a custom SequenceGenerator written for hibernate:
public class LoginGenerator extends SequenceGenerator {
#Autowired
ITicketService ticketService;
#Override
public Serializable generate(SessionImplementor session, Object obj) {
Ticket ticket = (Ticket) obj;
Long maxCounterOfSection = ticketService.findMaxSectionCounter(ticket
.getSection());
maxCounterOfSection++;
return ticket.getSection() + "-" + maxCounterOfSection;
}
}
But i dont have a spring context inside this generator! ticketService is null. i already tried #Component annotation for my generator, but without success.
PS: Im using spring 3.2.0-FINAL and hibernate 3.6.10-FINAL and there is no way updating to hibernate4!
Any idea, anyone?
Problem solved with ApplicationContextAware class, as described above.
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#SuppressWarnings("static-access")
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static <T> T getBean(Class<T> requiredType) {
return applicationContext.getBean(requiredType);
}
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
}
In applicationContext.xml I added <bean id="applicationContextProvider" class="de.gfz.rz.spring.ApplicationContextProvider"></bean>.
And here the usage:
public class LoginGenerator extends SequenceGenerator {
#Override
public Serializable generate(SessionImplementor session, Object obj) {
ITicketService ticketService = ApplicationContextProvider
.getBean(ITicketService.class);
Ticket ticket = (Ticket) obj;
Long maxCounterOfSection = ticketService.findMaxSectionCounter(ticket
.getSection());
maxCounterOfSection++;
return ticket.getSection() + "-" + maxCounterOfSection;
}
}

How to change XML-based Configuration to annotation configuration in Spring?

The class is as following:
class ReportControllerBase {
String reportName = "Report";
public String getReportName() {
return reportName;
}
public void setReportName(String reportName) {
this.reportName = reportName;
}
// ...
}
class AnnualReportController extends ReportControllerBase {
// ...
}
class SkinCareAnnualReprotController extends AnnualReportController {
String productName;
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
}
And the XML-based configuration is as following:
<bean id="annualReportController" class="AnnualReportController">
<property name="reportName" value="Annual Report"/>
</bean>
<bean id="annualSpecialReportController" class="AnnualReportController">
<property name="reportName" value="Annual Special Report"/>
</bean>
<bean id="skinCareAnnualReprotController" class="SkinCareAnnualReprotController" parent="annualReportController">
<property name="productName" value="A famous skin care product"/>
</bean>
The Bean annualReportController and annualSpecialReportController is the instance of the same Class. And skinCareAnnualReprotController is inherited from bean annualReportController.
How to implement this configuration in annotation-based configuration in Spring?
#Configuration
public class ReportConfiguration {
#Bean public AnnualReportController annualReportController() {
AnnualReportController annualReportController = new AnnualReportController();
annualReportController.setReportName("Annual Report");
return annualReportController;
}
#Bean public AnnualReportController annualSpecialReportController() {
AnnualReportController annualSpecialReportController = new AnnualReportController();
return withAnnualSpecialReportName(annualSpecialReportController);
}
#Bean public SkinCareAnnualReportController skinCareAnnualReportController() {
SkinCareAnnualReportController skinCareAnnualReportController = new SkinCareAnnualReportController();
skinCareAnnualReportController.setProductName("A famous skin care product");
return withAnnualSpecialReportName(skinCareAnnualReportController);
}
// in this instance, a helper method is arguably overkill,
// but I've included it for demonstration
private <T extends AnnualReportController> T withAnnualSpecialReportName(T report) {
report.setReportName("Annual Special Report");
return report;
}
}
Take a look at the Spring 3.1 documentation for more information.

How to test the destruction of session scoped beans in jUnit?

I have a session scoped bean in which I hold some user data and want to write a unit test to ensure that it remains session scoped.
I want to mock the starting and the ending of a session in jUnit and compare the values of the session scoped bean.
For now I have the following (rough drafts) of the unit test:
I use a custom context loader to register the session scope.
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.test.context.support.GenericXmlContextLoader;
import org.springframework.web.context.request.SessionScope;
public class SessionScopedGenericXmlContextLoader extends GenericXmlContextLoader {
#Override
protected void customizeBeanFactory(final DefaultListableBeanFactory beanFactory) {
beanFactory.registerScope("session", new SessionScope());
super.customizeBeanFactory(beanFactory);
}
}
The unit test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = SessionScopedGenericXmlContextLoader.class,
locations = { "classpath:/test-applicationContext.xml","classpath:/cache-config.xml" })
public class CachingTest extends AbstractJUnit4SpringContextTests {
// Session scoping
protected MockHttpSession session;
protected MockHttpServletRequest request;
ApplicationContext ctx;
CacheManager cacheManager;
Cache accountSettingsCache;
#Autowired
#Qualifier("cachedMethods")
DummyCacheMethods methods;
#Autowired
private SecurityContextHolder contextHolder;
protected void startRequest() {
request = new MockHttpServletRequest();
request.setSession(session);
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
}
protected void endRequest() {
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).requestCompleted();
RequestContextHolder.resetRequestAttributes();
request = null;
}
protected void startSession() {
session = new MockHttpSession();
}
protected void endSession() {
session.clearAttributes();
session = null;
}
#Before
public void constructSession() {
ctx = applicationContext;
cacheManager = (CacheManager) ctx.getBean("cacheManager");
accountSettingsCache = cacheManager.getCache("accountSettingsCache");
startRequest();
startSession();
}
#After
public void sessionClean() {
endRequest();
endSession();
contextHolder.clearContext();
}
#Test
// #DirtiesContext
public void checkSession1() {
final Authentication authentication = new Authentication() {
public String getName() {
return "Johny";
}
public void setAuthenticated(final boolean isAuthenticated) throws IllegalArgumentException {
}
public boolean isAuthenticated() {
return true;
}
public Object getPrincipal() {
final CustomUserDetails pr = new CustomUserDetails();
pr.setUsername("Johny");
return pr;
}
public Object getDetails() {
return null;
}
public Object getCredentials() {
return null;
}
public Collection<GrantedAuthority> getAuthorities() {
return null;
}
};
contextHolder.getContext().setAuthentication(authentication);
assertTrue(methods.getCurrentUserName().equals(accountSettingsCache.get("currentUser").get()));
assertTrue(methods.getCurrentUserName().equals(((CustomUserDetails) authentication.getPrincipal()).getUsername()));
}
#Test
// #DirtiesContext
public void testSession2() {
final Authentication authentication2 = new Authentication() {
public String getName() {
return "James";
}
public void setAuthenticated(final boolean isAuthenticated) throws IllegalArgumentException {
}
public boolean isAuthenticated() {
return true;
}
public Object getPrincipal() {
final CustomUserDetails pr = new CustomUserDetails();
pr.setUsername("James");
return pr;
}
public Object getDetails() {
return null;
}
public Object getCredentials() {
return null;
}
public Collection<GrantedAuthority> getAuthorities() {
return null;
}
};
SecurityContextHolder.setContext(contextHolder.getContext());
SecurityContextHolder.clearContext();
SecurityContextHolder.getContext().setAuthentication(authentication2);
assertTrue(methods.getCurrentUserName().equals(accountSettingsCache.get("currentUser").get()));
assertTrue(methods.getCurrentUserName().equals(((CustomUserDetails) authentication2.getPrincipal()).getUsername()));
}
#Test
public void testWiring() {
assertTrue("cacheManager is null", cacheManager != null);
assertTrue("accountSettingsCache is null", accountSettingsCache != null);
}
}
And the relevant function from DummyCachedMethods is:
#Cacheable(value = { "accountSettingsCache" }, key = "new String(\"currentUser\")")
public String getCurrentUserName() {
return WebUtils.getCurrentUser().getUsername();
}
WebUtils.getCurrentUser() just returns the current Principal from the SecurityContext.
But this does not work, the test does not pass at this line:
assertTrue(methods.getCurrentUserName().equals(((CustomUserDetails) authentication2.getPrincipal()).getUsername()));
Since the method call is cached, it still returns Johnny instead of James.
My cache related beans are:
<bean id="accountSettingsCache" class="org.springframework.cache.concurrent.ConcurrentMapCache" scope="session">
<constructor-arg>
<value>accountSettingsCache</value>
</constructor-arg>
<aop:scoped-proxy proxy-target-class="false" />
</bean>
<bean id="defaultCache" class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="defaultCache" />
<bean id="cacheManager" class="my.package.DynamicCacheManager" scope="session">
<property name="caches">
<set>
<ref bean="accountSettingsCache" />
<ref bean="defaultCache" />
</set>
</property>
<aop:scoped-proxy />
</bean>
accountSettingsCache is session scoped, I want to start a new session and destroy it.
It does pass if I uncomment the DirtiesContext annotations, but I guess it's not what I want.
What am I missing ?

Create a spring like wiring class

I want to create a bean that will act as a provider.
I will give it the class that it should return and the list of properties that I should set before returning it.
so basically it looks like this:
<bean id="somethingFactory" class="foo.bar.SomethingFactory">
<property name="implClass" value="foo.bar.SomehtingImpl" />
<property name="properties">
<props>
<prop key="prop1">prop1Value</prop>
<prop key="prop2">prop2Value</prop>
</props>
</property>
</bean>
The "SomethingFactory" has a provide() method that will return an instance of "SomehtingImpl".
The question is how can I use Spring to do it?
Make SomethingFactory a FactoryBean, extend AbstractFactoryBean and use a BeanWrapper to populate the properties from the input parameters.
Here's a sample implementation:
public class ServiceFactoryBean<T> extends AbstractFactoryBean<T> {
private Class<T> serviceType;
private Class<? extends T> implementationClass;
private Map<String, Object> beanProperties;
#Override
public void afterPropertiesSet() {
if (serviceType == null || implementationClass == null
|| !serviceType.isAssignableFrom(implementationClass)) {
throw new IllegalStateException();
}
}
#Override
public Class<?> getObjectType() {
return serviceType;
}
public void setBeanProperties(final Map<String, Object> beanProperties) {
this.beanProperties = beanProperties;
}
public void setImplementationClass(
final Class<? extends T> implementationClass) {
this.implementationClass = implementationClass;
}
public void setServiceType(final Class<T> serviceType) {
this.serviceType = serviceType;
}
#Override
protected T createInstance() throws Exception {
final T instance = implementationClass.newInstance();
if (beanProperties != null && !beanProperties.isEmpty()) {
final BeanWrapper wrapper = new BeanWrapperImpl(instance);
wrapper.setPropertyValues(beanProperties);
}
return instance;
}
}

Resources