Converting generic redis code to Azure Cache for Redis - spring-session

I have the following Spring Session code:
#Bean
public LettuceConnectionFactory connectionFactory() {
String hostName = AcmeProperty.getProperty("spring.redis.host", "localhost");
int port = Integer.parseInt(AcmeProperty.getProperty("spring.redis.port", "6379"));
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(hostName, port);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
It works just fine with the following settings when I'm running redis locally:
spring.redis.host=localhost
spring.redis.port=6379
However when I use Azure Cache for Redis with the following setting:
spring.redis.host=acmedev.redis.cache.windows.net
spring.redis.port=6380
I get this warning and the app hangs:
WARN (org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration:166) || - Unable to obtain SessionCookieConfig: Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml, a web-fragment.xml file nor annotated with #WebListener
What do I need to change to get this to work with Azure Cache for Redis?
I've tried this code, but the same thing happens:
#Bean
public JedisConnectionFactory connectionFactory() {
String hostName = AcmeProperty.getProperty("spring.redis.host", "localhost");
int port = Integer.parseInt(AcmeProperty.getProperty("spring.redis.port", "6379"));
String password = AcmeProperty.getProperty("spring.redis.password");
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLParameters sslParameters = new SSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
sslParameters.setProtocols(new String[]{"TLSv1.2"});
String uriStr = String.format("rediss://%s:%s", hostName, port);
URI uri = URI.create(uriStr);
JedisShardInfo shardInfo = new JedisShardInfo(uri, sslSocketFactory, sslParameters, null);
shardInfo.setPassword(password);
return new JedisConnectionFactory(shardInfo);
}

You need to use an XML Spring configuration; a Java configuration won't work. See "Unable to obtain SessionCookieConfig".
<util:constant id="configureRedisAction"
static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
<context:annotation-config/>
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"
p:configureRedisAction-ref="configureRedisAction"/>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="200" />
<property name="maxIdle" value="50" />
<property name="maxWaitMillis" value="30000" />
<property name="minIdle" value="10"/>
</bean>
<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${spring.redis.host}" />
<property name="port" value="${spring.redis.port}" />
<property name="poolConfig" ref="jedisPoolConfig" />
<property name="usePool" value="true" />
<property name="useSsl" value="${spring.redis.ssl}"/>
<property name="password" value="${spring.redis.password}"/>
</bean>

Related

Is Jasypt secure enough to use?

We are using Jasypt in one of our Spring based project to encrypt our database properties. As per Jasypt documentation we need to make algorith and password (secret) entry in our application context.
<bean id="environmentVariablesConfiguration"
class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<property name="algorithm" value="PBEWithMD5AndDES" />
<property name="passwordEnvName" value="secret" />
</bean>
<bean id="configurationEncryptor"
class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="config" ref="environmentVariablesConfiguration" />
</bean>
<bean id="propertyConfigurer"
class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor" />
<property name="location" value="classpath*:*.properties" />
</bean>
If we do that, any one can easily decrypt our properties by decrypt property provided by Jasypt only. For example
sh decrypt.sh input=pYmd0m1m2nEAGIeTtfdfdfdl/e3W49e password=sdsdfsf algorithm=PBEWithMD5AndDES
So how we can ensure the security of our property files.

Read time out spring web services

I am using spring web services framework to call some SOAP apis.
My configuration is like this:
<bean name="wsTemplate" class="org.springframework.ws.client.core.WebServiceTemplate" scope="prototype" >
<constructor-arg ref="messageFactory" />
<property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="unmarshaller"/>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
<property name="soapVersion">
<util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_11"/>
</property>
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" >
<property name="contextPaths">
<list>
some configured classes here
</list>
</property>
</bean>
<bean id="unmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" >
<property name="contextPaths">
<list>
some configured classes here
</list>
</property>
</bean>
Note I am using a prototype scope. I am not sure if that could be causing issues.
In my java code I use WebServiceTemplate like this:
#PostConstruct
private void init() {
try {
String uri = "https://web/file.svc?wsdl"
webServiceTemplate.setDefaultUri(uri);
} catch (Exception exception) {
logger.error("Error creating URL for the wsdl location.", exception);
}
}
I call the webservice like this:
Response response = (Response) webServiceTemplate.marshalSendAndReceive(request, new SoapActionCallback(SOAP_ACTION_URL));
I am getting the following read time out exception which I am not sure what it is, I have read it is because the response it is too big, but it really is not. It is not bigger than 100K
org.springframework.ws.client.WebServiceIOException: I/O error: Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
15:27:49,028 INFO [stdout] (default task-22) at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:561) ~[spring-ws-core-2.2.4.RELEASE.jar:2.2.4.RELEASE]
15:27:49,028 INFO [stdout] (default task-22) at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390) ~[spring-ws-core-2.2.4.RELEASE.jar:2.2.4.RELEASE]
15:27:49,028 INFO [stdout] (default task-22) at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:383) ~[spring-ws-core-2.2.4.RELEASE.jar:2.2.4.RELEASE]
What could be the issue ? I am clueless
At the end, I am not sure what was the issue, but I solved it by setting the message sender to a diferent provider . I set it to some apache library
<bean name="wsTemplate" class="org.springframework.ws.client.core.WebServiceTemplate" scope="prototype" >
<constructor-arg ref="messageFactory" />
<property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="unmarshaller"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender" />
</property>
</bean>

Having trouble getting Camel to use JDNI for database connection

I am having trouble getting Camel to work with jndi. I am deploying camel inside of IBM Websphere.
Inside of Websphere there is a jdni connection called "vzw.ds.commerce" that is setup to connect to the database I want to access.
This route below works:
<bean class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" id="publishDB">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:#//server.com:2051/mbschema" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
<bean id="commerceDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="vzw.ds.commerce" />
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="timer-to-console" customId="true">
<from uri="timer://foo?fixedRate=true&period=10s" />
<transform>
<simple>30004</simple>
</transform>
<process ref="createSQL" />
<to uri="jdbc:publishDB" />
<process ref="processSQL" />
<to uri="stream:out" />
</route>
</camelContext>
However, I want to use the jndi connection and not have the connection information in the route.
When I change the line to:
I get the error:
java.sql.SQLException: invalid arguments in call DSRA0010E: SQL State = null, Error Code = 17,433
The code I posted actually was correct. The problem I had was with the setup on Websphere.
Once I changed the setting on Websphere the code started working.

spring ldap security without xml

This documentation explains how to configure Spring-Security LDAP:
http://docs.spring.io/spring-security/site/docs/3.2.4.CI-SNAPSHOT/reference/htmlsingle/#ldap
3.4.5. Spring Bean Configuration
<bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
<property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
<property name="password" value="password"/>
</bean>
<bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSource"/>
<property name="userDnPatterns">
<list><value>uid={0},ou=people</value></list>
</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean
class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource"/>
<constructor-arg value="ou=groups"/>
<property name="groupRoleAttribute" value="ou"/>
</bean>
</constructor-arg>
</bean>
how can we achieve this without xml?
Here we have a sample which uses a local ldif file:
https://github.com/spring-projects/spring-security/blob/master/samples/ldap-jc/src/main/java/org/springframework/security/samples/config/SecurityConfig.java
I've modified SecurityConfig.java as follows:
public void registerGlobalAuthentication(AuthenticationManagerBuilder auth) throws Exception {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldap_url);
contextSource.setUrl(ldap_user);
contextSource.setPassword(ldap_password);
DefaultLdapAuthoritiesPopulator ldapAuthoritiesPopulator = new DefaultLdapAuthoritiesPopulator(contextSource, "ou=groups");
ldapAuthoritiesPopulator.setGroupRoleAttribute("ou");
LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthenticationProviderConfigurer = auth.ldapAuthentication();
ldapAuthenticationProviderConfigurer
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource(contextSource)
.ldapAuthoritiesPopulator(ldapAuthoritiesPopulator);
}
}
but when I login using the web form, I get this error:
java.lang.NullPointerException
at java.util.Hashtable.<init>(Hashtable.java:296)
at org.springframework.ldap.core.support.AbstractContextSource.getAuthenticatedEnv(AbstractContextSource.java:499)
at org.springframework.ldap.core.support.AbstractContextSource.doGetContext(AbstractContextSource.java:114)
at org.springframework.ldap.core.support.AbstractContextSource.getContext(AbstractContextSource.java:110)
at org.springframework.security.ldap.authentication.BindAuthenticator.bindWithDn(BindAuthenticator.java:112)
Is there a similar documentation to http://docs.spring.io/spring-security/site/docs/3.2.4.CI-SNAPSHOT/reference/htmlsingle/#ldap explaining how to achieve this without spring xml?
You need to call
contextSource.afterPropertiesSet()
if you are using the class outside an application context (see the source and Javadoc for Spring LDAP's AbstractContextSource for more information). Either that or you can just make it an #Bean and Spring will call the method and initialize it for you.
Also
contextSource.setUrl(ldap_user);
doesn't look right. Shouldn't that be setUserDn ?

How can I use the webadmin interface with an embedded Neo4j 2.0 instance?

I have a project which has been running with an embedded Neo4j 1.8.2 plus web admin interface.
Now I updated the project to run with the latest Neo4j 2.0.1. Although there were some obstacles during that course (as I'm utilizing Spring Data Neo4j) in the end everything went smooth.
But currently I'm stuck in getting the web admin running with it.
Any advise would be highly appreciated.
Here's my config which I was using for the 1.8 version
(class for configuration referenced in the snippets)
package com.example;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.MapConfiguration;
import org.neo4j.server.configuration.Configurator;
import org.neo4j.server.configuration.ThirdPartyJaxRsPackage;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Neo4jServerConfig implements Configurator {
private Configuration config;
public Neo4jServerConfig(Map<String, String> config) {
this.config = new MapConfiguration(config);
}
#Override
public Configuration configuration() {
return config;
}
#Override
public Map<String, String> getDatabaseTuningProperties() {
return null;
}
#Override
public Set<ThirdPartyJaxRsPackage> getThirdpartyJaxRsClasses() {
return new HashSet<>();
}
#Override
public Set<ThirdPartyJaxRsPackage> getThirdpartyJaxRsPackages() {
return new HashSet<>();
}
}
And the bean definitions
...
...
...
...
As mentioned ... this works as expected for the 1.8 embedded Neo4j.
But initialization under Neo4j 2.0 changed quite a bit. So I was forced to use the following bean definitions to get things running again
<!-- neo4j server configuration -->
<util:map id="neo4jConfig">
<entry key="allow_store_upgrade" value="true"/>
<entry key="enable_remote_shell" value="true"/>
<entry key="online_backup_enabled" value="true"/>
<entry key="node_auto_indexing" value="true"/>
<entry key="node_keys_indexable" value="id,name,type,__type__"/>
<entry key="relationship_auto_indexing" value="true"/>
</util:map>
<bean id="graphDbFactory" class="org.neo4j.graphdb.factory.GraphDatabaseFactory"/>
<bean id="graphDbBuilder" factory-bean="graphDbFactory" factory-method="newEmbeddedDatabaseBuilder">
<constructor-arg index="0" value="${neo4j.db.path}"/>
</bean>
<bean id="graphDbBuilderFinal" factory-bean="graphDbBuilder" factory-method="setConfig">
<constructor-arg ref="neo4jConfig"/>
</bean>
<bean id="graphDatabaseService" factory-bean="graphDbBuilderFinal" factory-method="newGraphDatabase" destroy-method="shutdown" />
After that I get error markers in this bean definition
<bean id="serverWrapper" class="org.neo4j.server.WrappingNeoServerBootstrapper" init-method="start" destroy-method="stop">
<constructor-arg index="0" ref="graphDatabaseService" />
<constructor-arg index="1" ref="config"/>
</bean>
First, the "org.neo4j.server.WrappingNeoServerBootstrapper" is now deprecated - are there any alternatives, I can use?
And secondly it complains about wrong constructor-arg "graphDatabaseService" ... it says "bean must be of org.neo4j.kernel.GraphDatabaseAPI" (which is also deprecated)
The server starts (at least what I can see from my jetty logs) without errors, but trying to browse to localhost:28473 ends up with no response.
Any clue?
Thanks in advance.
WrappingNeoServerBootstrapper & GraphDatabaseAPI are deprecated, but there is no alternitve for now ... So you have to use them.
For you, this a sample code of my application, where webadmin is started with an embedded neo4j 2.0.1 server :
val graphdb = new GraphDatabaseFactory()
.newEmbeddedDatabaseBuilder(DBPath)
.loadPropertiesFromFile(neo4jPropertiesPath)
.newGraphDatabase()
.asInstanceOf[GraphDatabaseAPI}
val srv = new WrappingNeoServerBootstrapper(graphdb, config);
srv.start()
So you must cast your "graphDatabaseService" to "GraphDatabaseAPI".
Sorry I don't khnow how to this with spring ... but you can do a wrapper of WrappingNeoServerBootstrapper with the good type.
Cheers
Took me longer than I care to admit to get this working. Please take a look at this pom for the dependencies, basically 2 includes for neo4j-server and 2 for Jersey. You also have to config the WrappingNeoServerBootstrapper (deprecated).
My POM excludes the CH.QOS logging stuff from Neo4J in favour of my own log configuration.
I've used Spring as well and have externalised most of the config. You can see that file here.
Once that little lot is done, simply access localhost on port 7474.
<util:map id="config">
<entry key="remote_shell_enabled" value="true"/>
</util:map>
<bean id="graphDbFactory" class="org.neo4j.graphdb.factory.GraphDatabaseFactory"/>
<bean id="graphDbBuilder" factory-bean="graphDbFactory" factory-method="newEmbeddedDatabaseBuilder">
<constructor-arg value="${neo4j.datastore}"/>
</bean>
<bean id="graphDbBuilderFinal" factory-bean="graphDbBuilder" factory-method="setConfig">
<constructor-arg ref="config"/>
</bean>
<bean id="graphDatabaseService" factory-bean="graphDbBuilderFinal" factory-method="newGraphDatabase"
destroy-method="shutdown"/>
<bean id="serverWrapper" class="org.neo4j.server.WrappingNeoServerBootstrapper" init-method="start"
destroy-method="stop">
<constructor-arg ref="graphDatabaseService"/>
</bean>
So verified this on OSX; Just to be clear once you add the POM updates and the spring configuration, that is all you need to do. Then just browsing to localhost:7474 gives you your object graph.

Resources