0
votes

I tried to implement dynamic database routing steps to my application. Everything works fine when "hibernate.hbm2ddl.auto" is none.

When I want to update my database scheme I change "hibernate.hbm2ddl.auto" to "update", and I get this error:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.preferredDatabaseSession': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]

I try to create my own RequestContextHolder, but it didn't work. I have a session scope bean, I guess I missed something.

My session scope class:

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class PreferredDatabaseSession implements Serializable {

private DatabaseEnvironment preferredDb;

public DatabaseEnvironment getPreferredDb() {
    return preferredDb;
}

public void setPreferredDb(DatabaseEnvironment preferredDb) {
    this.preferredDb = preferredDb;
}

}

I call it like:

public class DataSourceRouter extends AbstractRoutingDataSource {

    @Autowired
    private PreferredDatabaseSession db;

    @Override
    protected Object determineCurrentLookupKey() {
    return db.getPreferredDb();
    }
}

Also call from here:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private PreferredDatabaseSession userDatabaseSession;

private void setPreferredDatabase() throws DataAccessException {
    // String preferredDb = (String) request.getSession().getAttribute("preferredDb");
    String preferredDb = request.getParameter("preferredDb");
    if (preferredDb.equals(Constants.JPLATFORM)) {
        userDatabaseSession.setPreferredDb(DatabaseEnvironment.JPLATFORM);
    } else if (preferredDb.equals(Constants.TIGER)) {
        userDatabaseSession.setPreferredDb(DatabaseEnvironment.TIGER);
    }
}
}
1
why are you using session scope onPreferredDatabaseSession?stacker
@slimane because i want users select database at login page. Until they logout and select another database they should use same database after selection.can
I see, can you post any relevant code snippet where you are trying to access HTTP request information?stacker

1 Answers

0
votes

UserDetailsServiceImpl is a singleton bean but HttpServletRequest is a request scoped bean, that's what the exception is about.

try to use

ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = requestAttributes.getRequest();

instead of autowiring the HttpServletRequest

also fall to a default datasource when routing:

@Override
protected Object determineCurrentLookupKey() {
if (RequestContextHolder.getRequestAttributes() == null) {
    return DEFAULT_ONE;
}
return db.getPreferredDb();
}