I'm having below method and here caching TokenCache object.
#Cacheable(value = "TokenCache")
public TokenCache getToken(final String id) {
return getToken(id);
}
It was worked before adding the method param. I want to ignore method param in the cache.
After adding param, got below error
java.lang.ClassCastException: Invalid key type, expected : org.springframework.cache.interceptor.SimpleKey but was : java.lang.String
ehcache xml for reference
<cache alias="TokenCache">
<key-type>org.springframework.cache.interceptor.SimpleKey</key-type>
<value-type>com.test.TokenCache</value-type>
<expiry>
<ttl unit="minutes">60</ttl>
</expiry>
<listeners>
<listener>
//listeners
</listener>
</listeners>
<resources>
<heap>1</heap>
</resources>
</cache>
How to exclude method param in cache?
Related
In my Spring Integration webapp configuration I've added a property placeholder:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:ctx="http://www.springframework.org/schema/context"
...
xsi:schemaLocation="http://www.springframework.org/schema/context
...
">
<ctx:component-scan ... />
<ctx:annotation-config />
<mvc:annotation-driven />
<ctx:property-placeholder location="classpath:config.properties" trim-values="true" />
This is that file content:
apiPath=/requests
I'm sure this configuration works because I've tried using that value in a http inbound-channel-adapter:
<int-http:inbound-channel-adapter id="/api${apiPath}"
channel="httpRequestsChannel"
path="${apiPath}"
...>
</int-http:inbound-channel-adapter>
and if I change the property value the frontend application cannot reach the endpoint.
However, further in the context I have an endpoint so configured:
<int:header-value-router input-channel="httpRequestsChannel" ... >
<int:mapping value="POST" channel="httpRequestsPostChannel" />
...
</int:header-value-router>
<int:channel id="httpRequestsPostChannel" />
<int:chain input-channel="httpRequestsPostChannel">
<int:transformer method="transform">
<bean class="transformers.RequestToMessageFile" />
</int:transformer>
...
where I want to read the property value:
public class RequestToMessageFile {
#Autowired
private Environment env;
// ...
public Message<?> transform(LinkedMultiValueMap<String, Object> multipartRequest) {
System.out.println("Value: " + env.getProperty("apiPath"));
But on the console I see:
Value: null
I supposed once declared the property source in the XML that would be part of the whole web app environment, what am I missing? Should I declare the source in another place?
I noticed that if I add the following annotations:
#Configuration
#PropertySource("classpath:config.properties")
public class RequestToMessageFile {
the property is correctly found so I guess this is just a configuration problem.
In case it matters, here's the web.xml portion that configures integration:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/META-INF/spring.integration/context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
UPDATE
Partly following this answer I removed <ctx:property-placeholder> from the XML file and I added the following bean:
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#PropertySource("classpath:config.properties")
public class WebappConfig {
}
And now both beans and the XML file can see the properties.
Quoting Martin Deinum:
No it isn't a configuration issue that is how it is supposed to work. The doesn't add properties to the environment. Where as the #PropertySource does.
Therefore you should remove <ctx:property-placeholder> from your XML configuration. Continue to use #PropertySource("classpath:config.properties") and also add this bean definition:
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Pay attention how it has to be static do not load eagerly all other beans in the same #Configuration.
I am trying to integrate Ehcache with my Java Spring MVC Web Applications. I have followed the instructions from the following article:
https://dzone.com/articles/implementing-ehcache-using.
I have added the following dependency to my pom.xml file:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.9.0</version>
</dependency>
My ehcache.xml is as follows:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="swcmRestData"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300" timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
I have the following entries in my root-context.xml:
<!-- EhCache Configuration -->
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="classpath:ehcache.xml" p:shared="true"/>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache"/>
And I have a method for which I want to enable ehCache:
#Cacheable(value="swcmRestData", key="url")
public <T> T getEntity(String url, java.lang.Class<T> gt) throws RestException
{
T t = restClientService.getEntity(url, gt);
return t;
}
I want the data to be retrieved from the ehCache if the same url is passed to the specified method. I do not get any errors while running the code. But looks like the caching is not working. Is there anything that I am missing here
Two things that could be the cause of the problem:
You are missing the Spring configuration so that there is a link between the defined beans and the caching annotation. Effectively that's point 2 in the article you link which you do not mention here.
As suggested in comments, the method you are caching is called from within the same class. That's a limitation of Spring AOP implementation when using proxies. If you configure Spring to do bytecode weaving it will work.
If none of the above are the source of error, please provide more information on your setup.
environments: maven ,spring 4.2.4-RELEASE , 2 modules: zscb-server zscb-common ,and zscb-server dependent on zscb-common
my web.xml core code:
<listener>
<listener-class>com.iidooo.core.listener.RoleResourceInitListener</listener-class>
</listener>
i have a init listener in my module zscb-common:
RoleResourceInitListener core code:
public void contextInitialized(ServletContextEvent arg0) {
try {
ServletContext sc = arg0.getServletContext();
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) SpringUtil.getBean(sc, "sqlSessionFactory");
SqlSession sqlSession = sqlSessionFactory.openSession(true);
SecurityRoleMapper roleMapper = sqlSession.getMapper(SecurityRoleMapper.class);
List<SecurityRole> roleList = roleMapper.selectAll();
// key: roleID value:List<SecurityResource>
Map<Integer, List<SecurityResource>> roleResourceMap = new HashMap<Integer, List<SecurityResource>>();
for (SecurityRole item : roleList) {
roleResourceMap.put(item.getRoleID(), item.getResourceList());
}
sc.setAttribute(ServletConstant.ROLE_RESOURCE_MAP, roleResourceMap);
} catch (Exception e) {
e.printStackTrace();
logger.fatal(e);
}
}
my applicationContext.xml:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.iidooo.core.mapper com.edo.zscb.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
i have checked my mapper.xml's namepsace:
<mapper namespace="com.iidooo.core.mapper.SecurityRoleMapper">
and when i run tomcat, error occured
Mybatis Invalid bound statement (not found)
who can save me!
First result when googling MapperScannerConfigurer leads to the documentation stating:
The basePackage property can contain more than one package name,
separated by either commas or semicolons.
while your packages are separated by a space.
In Mybatis if you add a mapper in a way like getMapper(YourMapper.class) or addMapper(YourMapper.class), it is necessary to leave the relative YourMapper.xml inside the same source package.
In maven it is also necessary to include the xml file(s) as resources and they must be in same place of the generated .class file.
So it would be something like this inside the <build> section of your pom.xml file:
<build>
...
<resources>
<resource>
<filtering>false</filtering>
<directory>src</directory>
<includes>
<include>**/package_path/to/your/*.xml</include>
</includes>
</resource>
</resources>
...
</build>
With this configuration maven will leave .xml files in the same place as you have in your source tree.
I have this Ehcache XML configuration:
<ehcache>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskSpoolBufferSizeMB="30"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
</ehcache>
And also, I have some packages with entities (around 150). If I deploy my application on tomcat server, there is a lot WARN messages in log:
2015-04-29 11:59:02,712 [RMI TCP Connection(3)-127.0.0.1] WARN
org.hibernate.cache.ehcache.AbstractEhcacheRegionFactory - HHH020003:
Could not find a specific ehcache configuration for cache named
[com.company.project.entity.package.MyEntity]; using defaults.
I can write configuration for each entity -
<cache name="com.company.project.entity.package.MyEntity"
maxEntriesLocalHeap="50"
eternal="false"
overflowToDisk="false"
timeToLiveSeconds="120">
<persistence strategy="localTempSwap"/>
</cache>
But in this way, my configuration file become too large (1600 rows). I think there is exist another way to set default config to each entity and kill warn messages, but I don't know how to do it. If anybody know, please help. Many thanks.
This is the Hibernate EHCache Cache Region code that logs the warning message:
private Ehcache getCache(String name) throws CacheException {
try {
Ehcache cache = manager.getEhcache( name );
if ( cache == null ) {
LOG.unableToFindEhCacheConfiguration( name );
manager.addCache( name );
cache = manager.getEhcache( name );
LOG.debug( "started EHCache region: " + name );
}
HibernateEhcacheUtils.validateEhcache( cache );
return cache;
}
catch (net.sf.ehcache.CacheException e) {
throw new CacheException( e );
}
}
As you can see, you have two options:
You either declare the cache region in the ehcache.xml file.
You set the 'org.hibernate.cache.ehcache.AbstractEhcacheRegionFactory' log level to ERROR:
For Log4j2:
<Logger name="org.hibernate.cache.ehcache.AbstractEhcacheRegionFactory" level="error">
<AppenderRef ref="File"/>
</Logger>
One option would be to create a CacheObject base entity and configure that as your cache object.
Not the cleanest of solution but would remove the warnings without adding a large amount of config.
As the warning is just that, a warning personally i would just configure it to not show.
I'm currently trying the new REST DSL of the Apache Camel 2.14.0 release. And as the title of this post state it, I got a conflict with a String bean. Let's show what's wrong.
Here is a valid XML file reduced to a test case. It only defines a String bean and a Camel context containing a rest endpoint and a single route called by the rest endpoint.
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd"
>
<bean id="source-directory" class="java.lang.String">
<constructor-arg type="java.lang.String" value="file:/opt/a/directory/data/audio" />
</bean>
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
<dataFormats>
<json id="jack" library="Jackson" unmarshalTypeName="org.apache.camel.component.jackson.TestPojo"/>
</dataFormats>
<restConfiguration bindingMode="json" component="restlet" port="5117" />
<rest path="/rest-api/">
<get uri="/{words}/" consumes="application/json" produces="application/json">
<to uri="direct:words" />
</get>
</rest>
<route>
<from uri="direct:words" />
<transform>
<simple>${headers.words}</simple>
</transform>
</route>
</camelContext>
</beans>
To load and test this Camel context I use the following test case:
import org.apache.camel.CamelContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Test {
#org.junit.Test
public void testT() throws Exception {
final FileSystemXmlApplicationContext bean = new FileSystemXmlApplicationContext("src/test/resources/camelContext.xml");
final CamelContext context = bean.getBean("camelContext", CamelContext.class);
context.start();
Thread.yield();
Thread.sleep(600000);
}
}
It currently lead to the following error :
org.apache.camel.RuntimeCamelException: org.apache.camel.FailedToCreateRouteException: Failed to create route route2 at: >>> RestBinding <<< in route: Route(route2)[[From[rest:get:/rest-api/:/{words}/?produces=a... because of Provider com.sun.xml.bind.v2.ContextFactory could not be instantiated: javax.xml.bind.JAXBException: "file" ne contient pas ObjectFactory.class ou jaxb.index
That is, "file" does not contain ObjectFactory.class or jaxb.index
It seems that removing the source-directory bean declaration OR the rest endpoint declaration solves the problem, so it seems there is an incompatibility between them; but, as a Camel newbie, I'm unable to figure out what the problem is.
Can someone give me clues? Am I doing something wrong?
Thanks in advance,
Arthur.
I believe this issue is occurring due to the mechanism through which you are loading your Spring and Camel contexts for your unit test. Consider instead using CamelTestSupport.
I rewrote this test using this paradigm and everything worked just fine.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/META-INF/spring/camel-context.xml" })
public class Test extends CamelTestSupport {
#org.junit.Test
public void testT() throws Exception {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
CloseableHttpResponse response = httpClient.execute(new HttpGet(
"http://localhost:5117/rest-api/hello"));
assertEquals(200, response.getStatusLine().getStatusCode());
assertEquals("\"hello\"", new BufferedReader(new InputStreamReader(response.getEntity()
.getContent(), StandardCharsets.UTF_8)).readLine());
}
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder()
{
#Override
public void configure() throws Exception {
from("direct:words").transform().simple("${headers.words}");
}
};
}
}
Thanks to a teammate, I finally understood the error.
Problem come from the definition of a "java.lang.String" bean in the camel context.
When putting
<bean id="source" class="java.lang.String">
<constructor-arg type="java.lang.String" value="file:/opt/a/directory/data/audio" />
</bean>
in the camel context I got the following log :
[main] JaxbDataFormat INFO Creating JAXBContext with contextPath: file:/opt/a/directory/data/audio and ApplicationContextClassLoader: sun.misc.Launcher$AppClassLoader#3485def8
My understanding of the situation is that if any java.lang.String object is defined it is then used by the JAXBContext as a factory identifier. They probably seek for an #Autowired String attribute that is normally always null.
Replacing "source" bean by a bean that encapsulate my sting in an attribute solve the problem.
Unexpected side effect discovered !