How to properly inject ViewResolver? - spring

I'm trying to implement this solution but ViewResolver is not injected and it's null. I'm using Spring boot 2.x
get contents of processed JSP into spring controller without using HttpClient?
I already researched online and read documentation.
How do I properly inject the ViewResolver so the solution works?
#Service
public class SpringUtils {
private static final Logger LOG = Logger.getLogger(SpringUtils.class);
#Autowired private ViewResolver viewResolver;
#Autowired private LocaleResolver localeResolver;
public String renderView(HttpServletRequest request, ModelAndView mav) {
try {
View view = viewResolver.resolveViewName(mav.getViewName(), localeResolver.resolveLocale(request));
HttpServletResponse localResponse = new MyHttpServletResponseWrapper(new DummyResponse());
view.render(mav.getModel(), request, localResponse);
return localResponse.toString();
} catch (Exception e) {
return "";
}
}
public boolean doesViewExist(HttpServletRequest request, String viewName) {
try {
if (viewResolver.resolveViewName(viewName, localeResolver.resolveLocale(request)) != null) {
return true;
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
return false;
}
static class MyHttpServletResponseWrapper extends HttpServletResponseWrapper {
private StringWriter sw = new StringWriter();
public MyHttpServletResponseWrapper(HttpServletResponse response) {
super(response);
}
public PrintWriter getWriter() throws IOException {
return new PrintWriter(sw);
}
public ServletOutputStream getOutputStream() throws IOException {
throw new UnsupportedOperationException();
}
public String toString() {
return sw.toString();
}
}
}
Dummy Response
public class DummyResponse implements HttpServletResponse {
public DummyResponse() {
}
public void setAppCommitted(boolean appCommitted) {}
public boolean isAppCommitted() { return false; }
public int getContentCount() { return -1; }
public boolean getIncluded() { return false; }
public void setIncluded(boolean included) {}
public String getInfo() { return null; }
public ServletResponse getResponse() { return null; }
public OutputStream getStream() { return null; }
public void setStream(OutputStream stream) {}
public void setSuspended(boolean suspended) {}
public boolean isSuspended() { return false; }
public void setError() {}
public boolean isError() { return false; }
public ServletOutputStream createOutputStream() throws IOException {
return null;
}
public void finishResponse() throws IOException {}
public int getContentLength() { return -1; }
public String getContentType() { return null; }
public PrintWriter getReporter() { return null; }
public void recycle() {}
public void write(int b) throws IOException {}
public void write(byte b[]) throws IOException {}
public void write(byte b[], int off, int len) throws IOException {}
public void flushBuffer() throws IOException {}
public int getBufferSize() { return -1; }
public String getCharacterEncoding() { return null; }
public void setCharacterEncoding(String charEncoding) {}
public ServletOutputStream getOutputStream() throws IOException {
return null;
}
public Locale getLocale() { return null; }
public PrintWriter getWriter() throws IOException { return null; }
public boolean isCommitted() { return false; }
public void reset() {}
public void resetBuffer() {}
public void setBufferSize(int size) {}
public void setContentLength(int length) {}
public void setContentType(String type) {}
public void setLocale(Locale locale) {}
public Cookie[] getCookies() { return null; }
public String getHeader(String name) { return null; }
public Collection<String> getHeaders(String arg0) { return null; }
public Collection<String> getHeaderNames() { return null; };
public String[] getHeaderValues(String name) { return null; }
public String getMessage() { return null; }
public int getStatus() { return -1; }
public void reset(int status, String message) {}
public void addCookie(Cookie cookie) {}
public void addDateHeader(String name, long value) {}
public void addHeader(String name, String value) {}
public void addIntHeader(String name, int value) {}
public boolean containsHeader(String name) { return false; }
public String encodeRedirectURL(String url) { return null; }
public String encodeRedirectUrl(String url) { return null; }
public String encodeURL(String url) { return null; }
public String encodeUrl(String url) { return null; }
public void sendAcknowledgement() throws IOException {}
public void sendError(int status) throws IOException {}
public void sendError(int status, String message) throws IOException {}
public void sendRedirect(String location) throws IOException {}
public void setDateHeader(String name, long value) {}
public void setHeader(String name, String value) {}
public void setIntHeader(String name, int value) {}
public void setStatus(int status) {}
public void setStatus(int status, String message) {}
}

Related

Pass list of topics from application yml to KafkaListener

I have the following application.yml:
service:
kafka:
groupId: 345
consumer:
topics:
-
name: response
producer:
topics:
-
name: request1
num-partitions: 5
replication-factor: 1
-
name: request2
num-partitions: 3
replication-factor: 1
How can I access the list of topic names using spel for passing to KafkaListener annotation?
#KafkaListener(topics = "#{'${service.kafka.consumer.topics.name}'}", containerFactory = "kafkaListenerContainerFactory")
public void receive(String payload, #Header(KafkaHeaders.RECEIVED_TOPIC)String topic) {
Use configuration properties and collection projection...
#ConfigurationProperties("service.kafka.producer")
#Component
public class ConfigProps {
List<Topic> topics = new ArrayList<>();
public List<Topic> getTopics() {
return this.topics;
}
public void setTopics(List<Topic> topics) {
this.topics = topics;
}
#Override
public String toString() {
return "ConfigProps [topics=" + this.topics + "]";
}
public static class Topic {
private String name;
private int numPartitions;
private short replicationFactor;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getNumPartitions() {
return this.numPartitions;
}
public void setNumPartitions(int numPartitions) {
this.numPartitions = numPartitions;
}
public short getReplicationFactor() {
return this.replicationFactor;
}
public void setReplicationFactor(short replicationFactor) {
this.replicationFactor = replicationFactor;
}
#Override
public String toString() {
return "Topic [name=" + this.name + ", numPartitions=" + this.numPartitions + ", replicationFactor="
+ this.replicationFactor + "]";
}
}
}
and
#SpringBootApplication
public class So52741016Application {
public static void main(String[] args) {
SpringApplication.run(So52741016Application.class, args);
}
#KafkaListener(groupId = "${service.kafka.groupId}", topics = "#{configProps.topics.![name]}")
public void listener(String in) {
}
#Bean
public SmartLifecycle createTopics(KafkaAdmin admin, ConfigProps props) {
return new SmartLifecycle() {
#Override
public int getPhase() {
return Integer.MIN_VALUE;
}
#Override
public void stop() {
}
#Override
public void start() {
try (AdminClient client = AdminClient.create(admin.getConfig())) {
CreateTopicsResult createTopics = client.createTopics(props.topics.stream()
.map(t -> new NewTopic(t.getName(), t.getNumPartitions(), t.getReplicationFactor()))
.collect(Collectors.toList()));
createTopics.all().get();
}
catch (Exception e) {
// e.printStackTrace();
}
}
#Override
public boolean isRunning() {
return false;
}
#Override
public void stop(Runnable callback) {
}
#Override
public boolean isAutoStartup() {
return true;
}
};
}
}
and
2018-10-10 11:20:25.813 INFO 14979 --- [ntainer#0-0-C-1] o.s.k.l.KafkaMessageListenerContainer : partitions assigned: [request1-4, request2-0, request1-0, request2-1, request1-1, request2-2, request1-2, request1-3]
Of course, this is only the producer topics, but you can handle them all this way.

Webflux doesn't support ResponseBodyAdvice yet?

Since ResponseBodyAdvice interface is in web.servlet package
How could I implement such functions in webflux?
I also have this problem, i found it can be done by HandlerResultHandler.
For Example, I extend ResponseBodyResultHandler to wrap all my response
First, you should write ResponseWrapper.java
public class ResponseWrapper extends ResponseBodyResultHandler {
private static MethodParameter param;
static {
try {
//get new params
param = new MethodParameter(ResponseWrapper.class
.getDeclaredMethod("methodForParams"), -1);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public ResponseWrapper(List<HttpMessageWriter<?>> writers, RequestedContentTypeResolver resolver) {
super(writers, resolver);
}
private static Mono<Response> methodForParams() {
return null;
}
#Override
public boolean supports(HandlerResult result) {
boolean isMono = result.getReturnType().resolve() == Mono.class;
boolean isAlreadyResponse = result.getReturnType().resolveGeneric(0) == Response.class;
return isMono && !isAlreadyResponse;
}
#Override
#SuppressWarnings("unchecked")
public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
Preconditions.checkNotNull(result.getReturnValue(), "response is null!");
// modify the result as you want
Mono<Response> body = ((Mono<Object>) result.getReturnValue()).map(Response::success)
.defaultIfEmpty(Response.success());
return writeBody(body, param, exchange);
}
}
Then, add Bean in SpringBootApplication
#SpringBootApplication
public class SmartApplication {
#Autowired
ServerCodecConfigurer serverCodecConfigurer;
#Autowired
RequestedContentTypeResolver requestedContentTypeResolver;
#Bean
ResponseWrapper responseWrapper() {
return new ResponseWrapper(serverCodecConfigurer
.getWriters(), requestedContentTypeResolver);
}
//Spring start
public static void main(String[] args) {
SpringApplication.run(SmartApplication.class, args);
}
}
My response class, for reference
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Response<T> {
boolean success;
T data;
Object error;
String warning;
public Response() {
}
public static Response success() {
return success(null);
}
public static <T> Response success(T data) {
return new Response<T>().setSuccess(true).setData(data);
}
public static Response error(Throwable e) {
LogManager.getLogger(StackLocatorUtil.getCallerClass(2)).info(e);
return new Response().setSuccess(false).setError(e);
}
public static Response error(Object e) {
return new Response().setSuccess(false).setError(e);
}
public static Response error(String e) {
return new Response().setSuccess(false).setError(e);
}
/* get success */
public boolean isSuccess() {
return success;
}
/* set success */
public Response setSuccess(boolean success) {
this.success = success;
return this;
}
/* get data */
public Object getData() {
return data;
}
/* set data */
public Response setData(T data) {
this.data = data;
return this;
}
/* get error */
public Object getError() {
return error;
}
/* set error */
public Response setError(Object error) {
this.error = error;
return this;
}
}
i used ResponseBodyAdvise before spring 5.0. i think ResponseBodyResultHandler suport webflux since spring5.0.

What is the best way to use #ConfigurationProperties with Builders?

I have searched and can't find any examples that would show me a better way to do this, but in the Spring/Spring Boot code, there are generic builders but the builder itself seems to apply the properties programmatically. Here is some code trying to configure 2 Oracle Connection Pool Data Sources:
import oracle.ucp.jdbc.PoolDataSourceFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
#Configuration
#EnableConfigurationProperties
#ConditionalOnClass(PoolDataSourceFactory.class)
public class PersistenceAutoConfiguration {
#Bean (name = "readWriteDataSource")
public DataSource getReadWriteDataSource() throws SQLException {
OracleUcpDataSourceProperties rwProperties = getReadWriteProperties();
return OracleUcpDataSourceBuilder.create()
.connectionFactoryClassName(rwProperties.getConnectionFactoryClassName())
.url(rwProperties.getUrl())
.user(rwProperties.getUser())
.password(rwProperties.getPassword())
.initialPoolSize(rwProperties.getInitialPoolSize())
.minPoolSize(rwProperties.getMinPoolSize())
.maxPoolSize(rwProperties.getMaxPoolSize())
.connectionWaitTimeout(rwProperties.getConnectionWaitTimeout())
.inactiveConnectionTimeout(rwProperties.getInactiveConnectionTimeout())
.maxIdleTime(rwProperties.getMaxIdleTime())
.build();
}
#Bean (name = "readOnlyDataSource")
public DataSource getReadOnlyDataSource() throws SQLException {
OracleUcpDataSourceProperties roProperties = getReadOnlyProperties();
return OracleUcpDataSourceBuilder.create()
.connectionFactoryClassName(roProperties.getConnectionFactoryClassName())
.url(roProperties.getUrl())
.user(roProperties.getUser())
.password(roProperties.getPassword())
.initialPoolSize(roProperties.getInitialPoolSize())
.minPoolSize(roProperties.getMinPoolSize())
.maxPoolSize(roProperties.getMaxPoolSize())
.connectionWaitTimeout(roProperties.getConnectionWaitTimeout())
.inactiveConnectionTimeout(roProperties.getInactiveConnectionTimeout())
.maxIdleTime(roProperties.getMaxIdleTime())
.build();
}
#ConfigurationProperties(prefix = "datasource.readwrite")
#Bean(name = "readWriteProperties")
protected OracleUcpDataSourceProperties getReadWriteProperties() {
return new OracleUcpDataSourceProperties();
}
#ConfigurationProperties(prefix = "datasource.readonly")
#Bean(name = "readOnlyProperties")
protected OracleUcpDataSourceProperties getReadOnlyProperties() {
return new OracleUcpDataSourceProperties();
}
}
and
public class OracleUcpDataSourceProperties {
private String connectionFactoryClassName;
private String url;
private String user;
private String password;
private int initialPoolSize;
private int minPoolSize;
private int maxPoolSize;
private int connectionWaitTimeout;
private int inactiveConnectionTimeout;
private int maxIdleTime;
private Boolean validateConnectionOnBorrow;
public String getConnectionFactoryClassName() {
return connectionFactoryClassName;
}
public void setConnectionFactoryClassName(String connectionFactoryClassName) {
this.connectionFactoryClassName = connectionFactoryClassName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getInitialPoolSize() {
return initialPoolSize;
}
public void setInitialPoolSize(int initialPoolSize) {
this.initialPoolSize = initialPoolSize;
}
public int getMinPoolSize() {
return minPoolSize;
}
public void setMinPoolSize(int minPoolSize) {
this.minPoolSize = minPoolSize;
}
public int getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getConnectionWaitTimeout() {
return connectionWaitTimeout;
}
public void setConnectionWaitTimeout(int connectionWaitTimeout) {
this.connectionWaitTimeout = connectionWaitTimeout;
}
public int getInactiveConnectionTimeout() {
return inactiveConnectionTimeout;
}
public void setInactiveConnectionTimeout(int inactiveConnectionTimeout) {
this.inactiveConnectionTimeout = inactiveConnectionTimeout;
}
public int getMaxIdleTime() {
return maxIdleTime;
}
public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
}
public Boolean getValidateConnectionOnBorrow() {
return validateConnectionOnBorrow;
}
public void setValidateConnectionOnBorrow(Boolean validateConnectionOnBorrow) {
this.validateConnectionOnBorrow = validateConnectionOnBorrow;
}
}
and
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
import java.sql.SQLException;
public class OracleUcpDataSourceBuilder {
private PoolDataSource pds;
/**
* This will grab the pool factory and initialize it.
*/
public OracleUcpDataSourceBuilder() throws SQLException {
pds = PoolDataSourceFactory.getPoolDataSource();
}
public static OracleUcpDataSourceBuilder create() throws SQLException {
return new OracleUcpDataSourceBuilder();
}
public OracleUcpDataSourceBuilder connectionFactoryClassName(String connectionFactoryClassName) throws SQLException {
pds.setConnectionFactoryClassName(connectionFactoryClassName);
return this;
}
public OracleUcpDataSourceBuilder url(String url) throws SQLException {
pds.setURL(url);
return this;
}
public OracleUcpDataSourceBuilder user(String user) throws SQLException {
pds.setUser(user);
return this;
}
public OracleUcpDataSourceBuilder password(String password) throws SQLException {
pds.setPassword(password);
return this;
}
public OracleUcpDataSourceBuilder initialPoolSize(int initialPoolSize) throws SQLException {
pds.setInitialPoolSize(initialPoolSize);
return this;
}
public OracleUcpDataSourceBuilder minPoolSize(int minPoolSize) throws SQLException {
pds.setMinPoolSize(minPoolSize);
return this;
}
public OracleUcpDataSourceBuilder maxPoolSize(int maxPoolSize) throws SQLException {
pds.setMaxPoolSize(maxPoolSize);
return this;
}
public OracleUcpDataSourceBuilder connectionWaitTimeout(int connectionWaitTimeout) throws SQLException {
pds.setConnectionWaitTimeout(connectionWaitTimeout);
return this;
}
public OracleUcpDataSourceBuilder inactiveConnectionTimeout(int inactiveConnectionTime) throws SQLException {
pds.setInactiveConnectionTimeout(inactiveConnectionTime);
return this;
}
public OracleUcpDataSourceBuilder maxIdleTime(int maxIdleTime) throws SQLException {
pds.setMaxIdleTime(maxIdleTime);
return this;
}
public PoolDataSource build() {
return pds;
}
}
Preferably, I would like to be able to apply the properties directly to the builder in one place. is this possible? what changes would I have to make?
Thanks...
Here is your builder, sir
public class OracleUcpDataSourceBuilder {
private Map<String, String> properties = new HashMap<String, String>();
private static final String[] REQ_PROPERTIES = new String[] {"username", "password", "URL"};
public static OracleUcpDataSourceBuilder create() {
return new OracleUcpDataSourceBuilder();
}
public DataSource build() {
for (String prop : REQ_PROPERTIES) {
Assert.notNull(properties.get(prop), "Property is required:" + prop);
}
PoolDataSource result = PoolDataSourceFactory.getPoolDataSource();
bind(result);
return result;
}
private void bind(DataSource result) {
MutablePropertyValues properties = new MutablePropertyValues(this.properties);
new RelaxedDataBinder(result).bind(properties);
}
public OracleUcpDataSourceBuilder URL(String url) {
this.properties.put("URL", url);
return this;
}
public OracleUcpDataSourceBuilder username(String username) {
this.properties.put("username", username);
return this;
}
public OracleUcpDataSourceBuilder password(String password) {
this.properties.put("password", password);
return this;
}
}
Just define a bean like this:
#Bean (name = "readOnlyDataSource")
#ConfigurationProperties(prefix = "datasource.readonly")
public DataSource getReadOnlyDataSource() {
return OracleUcpDataSourceBuilder.create().build();
}
Just make sure that the property names are correct. Spring will take care of the rest.
Note: I use DataSourceBuilder or Spring as a reference.. You can check it's source code also.
Edit: Added some methods to make sure some properties are configured. But this way, you need to set those properties manually to make sure that they're available.

Problems with #Autowired, with a ManagedBean and an abstract class

Well, I have an abstract class like this:
public abstract class BasicCrudMBImpl<Bean, BO> extends BasicMBImpl {
protected Bean bean;
protected List<Bean> beans;
protected BO boPadrao;
public void deletar() {
try {
((BasicBO) boPadrao).delete((AbstractBean) bean);
addInfoMessage("Registro deletado com sucesso");
beans = retornaBeansDoBanco();
bean = null;
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
}
public void salvar(ActionEvent event) {
try {
if (((AbstractBean) bean).getId() == null) {
bean = (Bean) ((BasicBO) boPadrao).save((AbstractBean) bean);
addInfoMessage("Registro salvo com sucesso");
} else {
((BasicBO) boPadrao).update((AbstractBean) bean);
addInfoMessage("Registro atualizado com sucesso");
}
beans = retornaBeansDoBanco();
} catch (BOException e) {
FacesContext.getCurrentInstance().validationFailed();
addErrorMessage(e.getMessage());
}
}
public Bean getBean() {
return bean;
}
public void setBean(Bean bean) {
this.bean = bean;
}
public List<Bean> getBeans() {
try {
if (beans == null)
beans = (List<Bean>) retornaBeansDoBanco();
return beans;
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
return null;
}
public void setBeans(List<Bean> beans) {
this.beans = beans;
}
// Deve ser implementado para carregar a query adequada ao bean necessário
public abstract List<Bean> retornaBeansDoBanco();
public abstract void novo(ActionEvent event);
public abstract void alterar(ActionEvent event);
public BO getBoPadrao() {
return boPadrao;
}
public abstract void setBoPadrao(BO boPadrao);
public void addErrorMessage(String componentId, String errorMessage) {
addMessage(componentId, errorMessage, FacesMessage.SEVERITY_ERROR);
}
public void addErrorMessage(String errorMessage) {
addErrorMessage(null, errorMessage);
}
public void addInfoMessage(String componentId, String infoMessage) {
addMessage(componentId, infoMessage, FacesMessage.SEVERITY_INFO);
}
public void addInfoMessage(String infoMessage) {
addInfoMessage(null, infoMessage);
}
private void addMessage(String componentId, String errorMessage,
FacesMessage.Severity severity) {
FacesMessage message = new FacesMessage(errorMessage);
message.setSeverity(severity);
FacesContext.getCurrentInstance().addMessage(componentId, message);
}
}
In ManagedBean I tried to inject the "boPadrao" with #Autowired, like this:
#ManagedBean(name = "enderecoMB")
#ViewScoped
public class EnderecoMBImpl extends BasicCrudMBImpl<Endereco, BasicBO> {
private static Logger logger = Logger.getLogger(EnderecoMBImpl.class);
private List<TipoEndereco> tiposEndereco;
private List<Logradouro> logradouros;
#PostConstruct
public void init() {
logger.debug("Inicializando componentes no PostConstruct");
beans = retornaBeansDoBanco();
tiposEndereco = (List<TipoEndereco>) boPadrao
.findByNamedQuery(TipoEndereco.FIND_ALL);
logradouros = (List<Logradouro>) boPadrao
.findByNamedQuery(Logradouro.FIND_ALL_COMPLETO);
}
#Override
public List<Endereco> retornaBeansDoBanco() {
return (List<Endereco>) getBoPadrao().findByNamedQuery(Endereco.FIND_ALL_COMPLETO);
}
#Override
public void novo(ActionEvent event) {
bean = new Endereco();
}
#Override
public void alterar(ActionEvent event) {
// TODO Auto-generated method stub
}
public List<TipoEndereco> getTiposEndereco() {
return tiposEndereco;
}
public void setTiposEndereco(List<TipoEndereco> tiposEndereco) {
this.tiposEndereco = tiposEndereco;
}
public List<Logradouro> getLogradouros() {
return logradouros;
}
public void setLogradouros(List<Logradouro> logradouros) {
this.logradouros = logradouros;
}
#Autowired
public void setBoPadrao(BasicBO boPadrao) {
this.boPadrao = boPadrao;
}
}
But this doesn't works, the boPadrao is always null, getting a "NullPointerException". The error occurs in method retornaBeansDoBanco();

window scope in spring?

i was wondering about the spring scope equivalent to window scope ?
according to the documentation here
http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch04s04.html
i couldn't find any, so if there's a custom scope equivalent, can anyone please tell me, thanks.
EDIT: example of window scope in JSF
http://icefaces-showcase.icesoft.org/showcase.jsf?grp=compatMenu&exp=popup
One possible approach is having a session scoped bean that holds all the window sessions, and a window custom scope that access to the corresponding bean through that session scoped bean.
The required classes are:
Window Session
public class WindowSession {
private Map<String, Map<String,Object>> scopeMap = new HashMap<String, Map<String,Object>>();
private Map<String, Boolean> validSessions = new HashMap<String, Boolean>();
public WindowSession() {
super();
}
public Map<String, Map<String, Object>> getScopeMap() {
return scopeMap;
}
public void setScopeMap(Map<String, Map<String, Object>> scopeMap) {
this.scopeMap = scopeMap;
}
public Map<String, Boolean> getValidSessions() {
return validSessions;
}
public void setValidSessions(Map<String, Boolean> validSessions) {
this.validSessions = validSessions;
}
}
WindowIdContext
#Service
#Scope(value="request", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class WindowIdContext {
public static final String DEFAULT_SESSION_ID = "";
private String id = DEFAULT_SESSION_ID;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getQueryParamWithSessionId() {
if (DEFAULT_SESSION_ID.equals(id)) {
return "";
}
return "?" + WindowScope.WINDOW_ID_PARAM + "=" + id;
}
}
WindowSessionContext
#Service
#Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class WindowSessionContext {
private static SecureRandom random = new SecureRandom();
private WindowSession windowSession = new WindowSession();
#Autowired
private WindowIdContext windowIdContext;
public WindowSessionContext() {
windowSession.getValidSessions().put(WindowIdContext.DEFAULT_SESSION_ID, false);
}
public Object getObject(String name, ObjectFactory<?> objectFactory) {
String sessionId = windowIdContext.getId();
synchronized(this) {
if (!windowSession.getValidSessions().containsKey(sessionId)) {
windowSession.getValidSessions().put(sessionId, false);
}
Map<String,Object> sessionMap = windowSession.getScopeMap().get(sessionId);
if (sessionMap == null) {
sessionMap = new HashMap<String,Object>();
windowSession.getScopeMap().put(sessionId, sessionMap);
}
Object object = sessionMap.get(name);
if (object == null) {
object = objectFactory.getObject();
sessionMap.put(name, object);
}
return object;
}
}
public Object removeObject(String name) {
String sessionId = windowIdContext.getId();
synchronized(this) {
Map<String,Object> sessionMap = windowSession.getScopeMap().get(sessionId);
if (sessionMap == null) {
return null;
}
Object object = sessionMap.remove(name);
return object;
}
}
public String addSession() {
synchronized(this) {
String sessionId;
do {
sessionId = new BigInteger(130, random).toString(32);
} while (windowSession.getValidSessions().containsKey(sessionId));
windowSession.getValidSessions().put(sessionId, false);
return sessionId;
}
}
public void removeSession() {
String sessionId = windowIdContext.getId();
synchronized(this) {
windowSession.getScopeMap().remove(sessionId);
windowSession.getValidSessions().remove(sessionId);
}
}
public boolean isSessionValid(String sessionId) {
Boolean inUse = windowSession.getValidSessions().get(sessionId);
return inUse != null;
}
public boolean isSessionInUse(String sessionId) {
Boolean inUse = windowSession.getValidSessions().get(sessionId);
return inUse == true;
}
public synchronized boolean invalidateSession(String sessionId) {
Boolean valid = windowSession.getValidSessions().get(sessionId);
if (valid == null) {
return false;
}
if (sessionId.equals(WindowIdContext.DEFAULT_SESSION_ID)) {
windowSession.getValidSessions().put(sessionId, false);
} else {
windowSession.getValidSessions().remove(sessionId);
}
windowSession.getScopeMap().remove(sessionId);
for (Entry<String,Boolean> validSession : windowSession.getValidSessions().entrySet()) {
if (validSession.getValue() == true) {
return false;
}
}
return true;
}
public synchronized void setSessionInUse(String sessionId) {
windowSession.getValidSessions().put(sessionId, true);
}
public int getCount() {
return windowSession.getValidSessions().size();
}
}
WindowScope
public class WindowScope implements Scope {
private final int scope;
private static final int WINDOW_SCOPE = 40;
public static final String NAME = "window";
public static final String WINDOW_ID_PARAM = "windowid";
private ServletContext servletContext = null;
public WindowScope(ServletContext sc) {
servletContext = sc;
this.scope = WINDOW_SCOPE;
}
#Override
public Object get(String name, ObjectFactory<?> objectFactory) {
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
WindowSessionContext windowSessionContext = applicationContext.getBean(WindowSessionContext.class);
return windowSessionContext.getObject(name, objectFactory);
}
#Override
public Object remove(String name) {
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
WindowSessionContext windowSessionContext = applicationContext.getBean(WindowSessionContext.class);
return windowSessionContext.removeObject(name);
}
#Override
public String getConversationId() {
return RequestContextHolder.currentRequestAttributes().getSessionId();
}
#Override
public void registerDestructionCallback(String arg0, Runnable arg1) {
}
#Override
public Object resolveContextualObject(String key) {
return null;
}
protected int getScope() {
return this.scope;
}
}
WindowScopeFilter
#Component("windowScopeFilter")
public class WindowScopeFilter implements Filter {
#Autowired
private WindowSessionContext windowSessionContext;
#Autowired
private WindowIdContext windowIdContext;
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpServletResponse httpResponse = (HttpServletResponse)response;
String sessionId = httpRequest.getParameter(WindowScope.WINDOW_ID_PARAM);
if (sessionId != null) {
if (windowSessionContext.isSessionValid(sessionId)) {
windowIdContext.setId(sessionId);
} else {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
} else {
windowSessionContext.setSessionInUse(WindowIdContext.DEFAULT_SESSION_ID);
}
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
}
WindowScopeListener
#Component
public class WindowScopeListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
WebApplicationContext applicationContext = (WebApplicationContext)event.getApplicationContext();
Scope windowScope = new WindowScope(applicationContext.getServletContext());
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
beanFactory.registerScope("window", windowScope);
}
}
Source with complete source code: http://notwithoutmycode.com/post/window/scope/in/spring

Resources