thymeleaf error - thymeleaf

Below code throw error of unresolvable circular reference. when Spring is trying to create bean of MessageFormatHelper class.This error throw while I run the jar. I try to see but not getting what is reason. Could anyone help.
First class,
#Component
class DbTemplateResolver extends TemplateResolver {
#Autowired
SpringTemplateEngine templateEngine;
....othercode
#PostConstruct
public void extension() {
templateEngine.addTemplateResolver(this);
}
...other code
}
Second class,
#Component
class MessageFormatHelper{
#Autowired
SpringTemplateEngine templateEngine;
... other code
String getMessage()
{
final Context ctx = new Context(locale);
ctx.setVariable("contractMap", model.get(ContractMap.TEMPLATE_MODEL_MAP_KEY));
mergedMessage = templateEngine.process(fileName, ctx);
}
}
Full error:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.flex.eventManagement.handler.helper.MessageFormatHelper com.flex.eventManagement.handler.helper.NotificationPreProcessor.messageFormatHelper; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageFormatHelper': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.thymeleaf.spring4.SpringTemplateEngine com.flex.eventManagement.handler.helper.MessageFormatHelper.templateEngine; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration$ThymeleafDefaultConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private final java.util.Collection org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration$ThymeleafDefaultConfiguration.templateResolvers; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dbTemplateResolver': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.thymeleaf.spring4.SpringTemplateEngine com.flex.eventManagement.handler.helper.DbTemplateResolver.templateEngine; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'templateEngine': Requested bean is currently in creation: Is there an unresolvable circular reference?
Updated
Remove template engine auto-wire from DbTemplateResolver class. Autowire into MessageFormatHelper.java class like below
class MessageFormatHelper{
#Bean
public DbTemplateResolver dbTemplateResolver() {
DbTemplateResolver resolver = new DbTemplateResolver();
resolver.setOrder(2);
return resolver;
}
#Bean
public SpringTemplateEngine thymeleafTemplateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolvers(Sets.newHashSet(dbTemplateResolver()));
return engine;
}
}
Also I need to remove SpringTemplateEngine auto wired from MessageFormatHelper right? so how can I call mergedMessage = templateEngine.process(fileName, ctx);?
Update 2.
should followed required in MessageFormatHelper
#Autowired
DbTemplateResolver dbTemplateResolver;
#Autowired
SpringTemplateEngine templateEngine;
#PostConstruct
public void extension() {
templateEngine.addTemplateResolver(dbTemplateResolver);
}

Your code is flawed and it seems you lack basic understanding of how Spring works and how you should use Spring to configure things.
First you are using Spring Boot and want to use Thymeleaf. This is simply done by added the spring-boot-starter-thymeleaf as a dependency for you project. (I assume you have already done this).
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf<artifactId>
</dependency>
Spring Boot detects the fact that you have Thymeleaf on your classpath and the ThymeleafAutoConfiguration will kick in and configure the SpringTemplateEngine for you. It will even detect every bean of the type ITemplateResolver, which I assume your DbTemplateResolver implements.
The only thing to have your DbTemplateResolver add is to add a #Bean method to an #Configuration (or your application) class.
#Bean
public ITemplateResolver dbTemplateResolver() {
return new DbTemplateResolver();
}
Spring will detect it and inject it into the automatically configured SpringTemplateEngine.
The only thing you need to do is in classes you need the SpringTemplateEngine you need to auto wire it. Just use the super class not the concrete type.
#Autowired
private TemplateEngine templateEngine;
Don't mess around with trying to configure it later on, use the framework for that.

Related

Spring Security LDAP Changes After 5.7

I am trying to understand the steps to support LDAP with Spring security...replacing our current basic authentication. Recently I made the changes to support the deprecation of the WebSecurityConfigurerAdapter and all is working fine. So now I want to swap out the basic authentication AuthenticationManager or AuthenticationProvider with their LDAP equivalents. There are several websites with partial information and I cant quite put the pieces together.
So I am starting with the spring guide on authenticating ldap (https://github.com/spring-guides/gs-authenticating-ldap) I took the "complete" example, modified for our version of Spring Boot 2.7.5 and the app starts and validates fine. I tried updating the example according to several websites from :
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org")
.and()
.passwordCompare()
.passwordEncoder(new BCryptPasswordEncoder())
.passwordAttribute("userPassword");
To :
#Bean
public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean =
EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
contextSourceFactoryBean.setPort(0);
return contextSourceFactoryBean;
}
#Bean
public AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
LdapPasswordComparisonAuthenticationManagerFactory factory = new LdapPasswordComparisonAuthenticationManagerFactory(
contextSource, new BCryptPasswordEncoder());
factory.setUserDnPatterns("uid={0},ou=people");
factory.setPasswordAttribute("pwd");
return factory.createAuthenticationManager();
}
Thinking this closer to the recommendations and closer to what I would be using in our real project. Now when I try to build ... the test phase keeps failing with the following stack trace
ERROR[m] loginWithValidUserThenAuthenticated Time elapsed: 0 s <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'authenticationManager' defined in class path resource [com/example/authenticatingldap/WebSecurityConfig.class]: Unsatisfied dependency expressed through method 'authenticationManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextSourceFactoryBean': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Unable to load LDIF classpath*:*.ldif
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextSourceFactoryBean': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Unable to load LDIF classpath*:*.ldif
Caused by: java.lang.IllegalStateException: Unable to load LDIF classpath*:*.ldif
Caused by: com.unboundid.ldap.sdk.LDAPException: An entry with DN 'dc=springframework,dc=org' already exists in the server.
I am using the same ldif file that worked with the other configuration. The code follows the other examples and recommendation but the embedded LDAP server wont load the file. Has anyone seen and solved this problem? Once this is working, do we simply remove the Embedded LDAP bean and somehow point the configuration to the real LDAP server?

clientRegistrationRepository cannot be null

Keycloak OAuth 2.0 clientRegistrationRepository cannot be null.
Hello, discovered a problem, when trying to make use of OAuth 2.0 in my application. It fails after the startup. Message:
Exception encountered during context initialization - cancelling
refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration':
Unsatisfied dependency expressed through method
'setSecurityWebFilterChains' parameter 0; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'springSecurityFilterChain' defined in class
path resource
[com/microservices/apigateway/security/SecurityConfig.class]: Bean
instantiation via factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate
[org.springframework.security.web.server.SecurityWebFilterChain]:
Factory method 'springSecurityFilterChain' threw exception; nested
exception is java.lang.IllegalArgumentException:
clientRegistrationRepository cannot be null
Cannot find any info in the net about the possible nature of this problem.
SecurityConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
#Configuration
#EnableWebFluxSecurity
public class SecurityConfig {
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.pathMatchers("/actuator/**")
.permitAll()
.and()
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.oauth2Login() // to redirect to oauth2 login page.
;
return http.build();
}
}
application.properties
spring.application.name=api-gateway
server.port=8765
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
#spring.cloud.gateway.discovery.locator.enabled=true
#spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true
spring.sleuth.sampler.probability=1.0
spring.security.oauth2.client.provider.myprovider.issuer-uri=http://localhost:8083/realms/MyMicroservicesRealm
spring.security.oauth2.client.provider.myprovider.authorization-uri=http://localhost:8083/realms/MyMicroservicesRealm/protocol/openid-connect/auth
spring.security.oauth2.client.provider.myprovider.token-uri=http://localhost:8083/realms/MyMicroservicesRealm/protocol/openid-connect/token
spring.security.oauth2.client.provider.myprovider.jwk-set-uri=http://localhost:8083/realms/MyMicroservicesRealm/protocol/openid-connect/certs
spring.security.oauth2.client.provider.myprovider.user-info-uri=http://localhost:8083/realms/MyMicroservicesRealm/protocol/openid-connect/userinfo
spring.security.oauth2.client.provider.mywebclient.user-name-attribute = preferred_username
spring.security.oauth2.client.registration.myclient.provider=myprovider
spring.security.oauth2.client.registration.myclient.scope=openid, profile, roles
spring.security.oauth2.client.registration.myclient.client-id=gateway-client
spring.security.oauth2.client.registration.myclient.client-secret=ajKhFIsMi3qJNlXkVTS8AFhYwhv3TUSh
spring.security.oauth2.client.registration.myclient.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.myclient.redirect-uri="{baseUrl}/login/oauth2/code/keycloak"
logging.level.org.springframework.security.web=DEBUG
Resolved by removing spring-boot-starter-web dependency

Auto-wiring generic dependency to a specific type

I have a class like this,
#Component
class GenericRepositoryModel<T>
{
//.,..
}
In my code, I have to use for a specific type,
#Controller
class WebController
{
#Autowired
private GenericRepositoryModel<Type1> customerRepository;
}
But when I try to do the above, I am getting the below exception.
Field customerRepository in com.sbexample.springbootdemo.WebController
required a bean of type
'com.sbexample.springbootdemo.GenericRepositoryModel' that could not
be found. Consider defining a bean of type
'com.sbexample.springbootdemo.GenericRepositoryModel' in your
configuration.
What's the right way of doing it?
BTW, I am using Spring 4.3.16 via Spring boot 1.5.10.

Can't convert from #stateless to #stateful beans

I'm having a problem instantiating a stateful session bean on glassfish3.1.
A #ManagedBean (session scoped) of a JSF application used to use a #Local interface of a #Stateless session bean and everything worked fine.
Now I had to convert to a #Stateful bean and I'm getting an exception when I try to inject the stateful bean into the mannaged bean.
The code in question consists of the following 3 layers:
#ManagedBean
#SessionScoped
public class ShopBean {
private #EJB ShopAdminInterface sa;
...
}
#Local
public interface ShopAdminInterface {
.... some interfaces
}
#Stateful
public class ShopAdmin implements ShopAdminInterface {
#EJB CoreClassEAO s;
... some implementation
}
The CoreClassEAO presents an access layer to the database and looks like this:
#Stateful
public class CoreClassEAO {
#PersistenceContext
EntityManager em;
.... access to my persistence interface
}
In the last version, when the ShopAdmin and CoreClassEAO both were #Stateless beans everything worked perfectly. But now, injecting ShopAdminInterface throws an exception at me
Update: I narrowed down the problem: See my other question
Injecting #Stateful bean into another #Stateful bean

Inject a stateless EJB with #Inject into CDI Weld ManagedBean (JSF 1.2 EJB Application on jboss 6 AS)

Currently I am trying to inject a stateless EJB into a CDI managed controller on Jboss 6 AS Final. The controller is managed in the context an accessible from the JSF pages. If I inject the stateless bean with #EJB it is working. If I inject the stateless EJB with #Inject I get the following Exception:
My controller:
#Named("TestController")
public class TestController {
#Inject
private TestManagerLocal myTestManager;
...
}
}
My stateless bean:
#SuppressWarnings("unchecked")
#Stateless
public class TestManagerBean implements TestManagerLocal {
#PersistenceContext
private EntityManager em;
...
}
The Interface of the Bean is annotated with #Local.
If I try to call myTestManager I get the following exception:
WELD-000079 Could not find the EJB in JNDI: class
de.crud.org$jboss$weld$bean-jboss$classloader:id="vfs:$$$usr$local$jboss$server$default$deploy$test$ear"-SessionBean-TestManagerBean_$$_WeldProxy
THX a lot.
For those not having the luxury to change an ear to a war, I've found the following workaround:
Create an EJB in the war
Inject that EJB with the EJBs from the EJB module
Add CDI producer methods
Qualify #Inject with the qualifier for those producer methods:
Code:
// This bean is defined in the WEB module
#Stateless
public class EJBFactory {
#EJB
protected UserDAO userDAO;
// ~X other EJBs injected here
#Produces #EJBBean
public UserDAO getUserDAO() {
return userDAO;
}
// ~X other producer methods here
}
Now EJBs from anywhere in the EAR can be injected with:
// This bean is also defined in the web module
#RequestScoped
public class MyBean {
#Inject #EJBBean
private UserDAO userDAO; // injection works
public void test() {
userDao.getByID(...); // works
}
}
EJBBean is a simple standard qualifier annotation. For completeness, here it is:
#Qualifier
#Retention(RUNTIME)
#Target({TYPE, METHOD, FIELD, PARAMETER})
public #interface EJBBean {
}
The problem was, that I built and deployed my application as an ear. Weld is working when I deploy my application as an war including all EJBs.
Currently there are various problems arising from the fact that WARs in EAR-Deployments don't share the same classloader. See https://issues.jboss.org/browse/JBAS-8683 for the ongoing discussion in the JBoss-AS JIRA (and vote it up :-) )
UPDATE I found this information on how to disable separate classloaders, option 1 worked for me, but be extremely careful with this. The separation of classloaders hasn't been introduced for no reason, so apparently there are new problems on the road ahead...

Resources