To use simple Spring Cache based on Map logic we need to do two things:
1. Add cacheManager in our application context:
<cache:annotation-driven cache-manager="cacheManager"/>
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
p:name="sourceSystemsCache/>
// add more caches
</set>
</property>
</bean>
2. In bean add annotation above method:
@Cacheable("cacheName") // in our case sourceSystemsCache
public int doSomething(int i) {..}
Note: besides cache name, you can indicate which values not to cache (usually using spring spel) etc.
Also useful is to reset cache which can be done using fake method or method that deletes date from db and we in out case delete it from our cache.
@CacheEvict(value = "cacheName", beforeInvocation = true)
public void deleteCacheName() { //do nothing }
@CacheEvict(value = "userCache", beforeInvocation = true)
public void deleteUserName(User user) { dao.delete(user); }
I had a task to reset all cache using rest, so I wrote service where I have autowired SimpleCacheManager and took its all cacheNames it contained and just cleared them:
public class CacheServiceImpl implements CacheService {
@Autowired
private SimpleCacheManager manager;
@Override
public boolean resetCache() {
for (String cacheName : manager.getCaheNames()) {
manager.getCache(cacheName).clear();
}
}
}
Thursday, 19 November 2015
Monday, 16 November 2015
Why yoda time?
Original - https://mestachs.wordpress.com/tag/jodatime/
Don’t use java built-in classes, use jodatime and enforce this rule with sonar !
Don’t use java built-in classes
How many bugs in 5 lines of code ?
Date date = new Date(2007, 12, 13, 16, 40); TimeZone zone = TimeZone.getInstance("Europe/Bruxelles"); Calendar cal = new GregorianCalendar(date, zone); DateFormat fm = new SimpleDateFormat("HH:mm Z"); String str = fm.format(cal);
Just 6 bugs !
int year = 2007 - 1900; int month = 12 - 1; Date date = new Date(year, month, 13, 16, 40); TimeZone zone = TimeZone.getInstance("Europe/Brussels"); Calendar cal = new GregorianCalendar(zone); cal.setTime(date); DateFormat fm = new SimpleDateFormat("HH:mm Z"); fm.setTimeZone(zone); Date calDate = cal.getTime(); String str = fm.format(calDate);
If you want deeper explanations see this [presentation]
java.util.Date issues
- From JDK1.0
- Uses two digit years (from 1900)
- January is 0, December is 11
- Should have been immutable
- Most methods deprecated in JDK1.1
- Uses milliseconds from 1970 representation
java.util.Calendar issues
- From JDK1.1
- Uses subclasses for different calendar systems
- January is 0, December is 11
- Should have been immutable
- Uses dual representation internally
- value for each field
- milliseconds from 1970 representation
- Odd performance and bugs
java.util.DateFormat issues
- Pattern based date formatting
- “dd MMM yyyy”
- Requires Date object
- Not thread-safe : see rule findbugs : Multithreaded correctness – Call to static DateFormat
- Not especially fast
- Sun RFE to make thread-safe ignored
SQL – java.util.sql.Date, Time, Timestamp issues
Subclass java.util.Date
- Date extends Date (!)
- Time extends Date (!)
- Override superclass to block methods (throws Exception)
- Timestamp adds nanoseconds
- equals() broken
- All the problems of java.util.Date and more
- timezone problem new Time(long)
Avoid millis manipulation and let’s use Jodatime !
when playing with java.util.Date you end up doing calculation in millis
int
days =
40
;
Date now =
new
Date();
long
nowMillis = now.getTime();
Timestamp nowTimestamp =
new
Timestamp(nowMillis);
long
future =
3600
*
24
* days *
1000
;
Timestamp expiryTimestamp =
new
Timestamp(nowMillis + future);
System.out.println(
"nowTimestamp "
+ nowTimestamp);
System.out.println(
"expiryTimestamp "
+ expiryTimestamp);
this last code sample contains a bug… int vs long for days !
see this explaination the expiryTimestamp is before the nowTimestamp for “large days count”
nowTimestamp 2011-02-04 12:45:40.381
expiryTimestamp 2011-01-25 19:42:53.085
now let’s write the same code with joda time
DateTime nowTimestamp2 =
new
DateTime();
System.out.println(
"nowTimestamp "
+ nowTimestamp2);
System.out.println(
"expiryTimestamp "
+ nowTimestamp2.plusDays(days));
it’s more readable… and most important it return the correct value ;)
nowTimestamp 2011-02-04T12:45:40.443+01:00
expiryTimestamp 2011-03-16T12:45:40.443+01:00
Sonar to the rescue
sonar can detect these issues :
- Multithreaded correctness – Call to static Calendar
- Multithreaded correctness – Call to static DateFormat
to fix them with jodatime let’s use the DateTimeFormat.
fmt
=DateTimeFormat.forPattern("MMMM, yyyy");DateTime datetime = fmt.parseDateTime(duedate);
this one is threadsafe and can be static and final field. or use the toString
datetime.toString("dd:MM:yy");
but the step further is to banish jdk date from your code base !
To do so, let’s define sonar architectural constraint like
To do so, let’s define sonar architectural constraint like
- Arch : avoid java.util.GregorianCalendar
- Arch : avoid java.util.Date
- Arch : avoid java.text.SimpleDateFormat
- Arch : avoid java.sql.Timestamp
- Arch : avoid java.sql.Date
to banish jdk dates from your model, you may implement hibernate usertype, jaxb adapter,…
Tuesday, 6 October 2015
Why we need serialVersionUID and how to generate it?
Why?
The best answer is from Java doc for
The best answer is from Java doc for
java.io.Serializable
In two words:
1. helps to check if class version during deserialization is the same;
2. should be private;
3. is better than generated as the last one can cause errors.
The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an
InvalidClassException
. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID
" that must be static, final, and of type long
:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected
InvalidClassExceptions
during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members.
How to generate it?
Basically any number but Intellij Idea can generate it for you:
File -> Settings ->Inspections -> Java -> Serialization issues:
check Serializable class without 'serialVersionUID'
Once changes are applied, Intellij Idea will warn you that your class without serialVersionUID and suggest to generate it for you :)
Thursday, 10 September 2015
How to mock static methods during unit testing?
Well, static mock is not implemented in Mockito, so we have to use PowerMock to achieve this:
Let's say we have the following class:
and we need to test that UnknownHostException is thrown.
So our goal is to mock InetAddress.getLocalHost() and ask it to return an exception so SystemUtils.getHostName() will return 'Unknown'.
First import all needful libs:
And test would look the following way:
Let's say we have the following class:
package com;
import java.net.InetAddress;
import java.net.UnknownHostException;
public final class SystemUtils {
public static final String UNKNOWN_HOST = "Unknown";
public static String getHostName() {
String hostname = UNKNOWN_HOST;
try {
InetAddress addr = InetAddress.getLocalHost();
// Get hostname
hostname = addr.getHostName();
} catch (UnknownHostException e ) {
System.out.println("catch UnknownHostException...");
}
return hostname;
}
}
import java.net.InetAddress;
import java.net.UnknownHostException;
public final class SystemUtils {
public static final String UNKNOWN_HOST = "Unknown";
public static String getHostName() {
String hostname = UNKNOWN_HOST;
try {
InetAddress addr = InetAddress.getLocalHost();
// Get hostname
hostname = addr.getHostName();
} catch (UnknownHostException e ) {
System.out.println("catch UnknownHostException...");
}
return hostname;
}
}
and we need to test that UnknownHostException is thrown.
So our goal is to mock InetAddress.getLocalHost() and ask it to return an exception so SystemUtils.getHostName() will return 'Unknown'.
First import all needful libs:
<properties> <junit.version>4.11</junit.version> <mockito.version>1.10.19</mockito.version> <powermock.version>1.6.2</powermock.version> </properties>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
And test would look the following way:
import com.SystemUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.internal.stubbing.answers.ThrowsExceptionClass; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.net.InetAddress; import java.net.UnknownHostException; import static org.junit.Assert.assertEquals; @RunWith(PowerMockRunner.class) @PrepareForTest(SystemUtils.class) public class SystemUtilsTest { @Test public void testGetHostName() throws UnknownHostException { PowerMockito.mockStatic(InetAddress.class); PowerMockito.when(InetAddress.getLocalHost()) .then(new ThrowsExceptionClass(UnknownHostException.class)); String actualValue = SystemUtils.getHostName(); assertEquals("On exception expected unknown value", SystemUtils.UNKNOWN_HOST, actualValue); } }
How to set log file with custom name in log4j2?
Sometimes having log4j2.xml file with default naming can be a problem if several projects share the same classpath. In order to change logger file at runtime the below method can be used:
public static void logAppInfo(String configFileName) { URL fileUrl = SLF4JHello.class.getClassLoader().getResource(configFileName); if (fileUrl == null) { throw new RuntimeException("File not found: " + configFileName); } try { LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false); loggerContext.setConfigLocation(fileUrl.toURI()); loggerContext.updateLoggers(); } catch (URISyntaxException e) { e.printStackTrace(); } }
How to enable smart import in Intellij Idea 14?
To enable auto-import and auto optimize imports go to:
Intellij Idea 14 -> Settings -> Editor -> General -> Auto Import
and check two options:
1. Optimize import on the fly
2. Add unambiguous imports on the fly
Intellij Idea 14 -> Settings -> Editor -> General -> Auto Import
and check two options:
1. Optimize import on the fly
2. Add unambiguous imports on the fly
Tuesday, 14 July 2015
How to set timezone in Weblogic?
1. Open file in Notepad
../{your_weblogic_folder}/user_projects/domains/{your_domain_name}/bin/setDomainEnv.cmd
2. Add to the property %JAVA_PROPERTIES% -Duser.timezone=GMT.
Line should look the following way:
set JAVA_PROPERTIES=%JAVA_PROPERTIES% %EXTRA_JAVA_PROPERTIES% -Duser.timezone=GMT
../{your_weblogic_folder}/user_projects/domains/{your_domain_name}/bin/setDomainEnv.cmd
2. Add to the property %JAVA_PROPERTIES% -Duser.timezone=GMT.
Line should look the following way:
set JAVA_PROPERTIES=%JAVA_PROPERTIES% %EXTRA_JAVA_PROPERTIES% -Duser.timezone=GMT
Friday, 3 July 2015
How to write / read BLOB to / from Oracle database?
WRITE:
To transform String value into blob just execute your_string.getBytes();
String blobValue = "long blob";
bytes[] bytes = blobValue.getBytes();
int rows = getJdbcTemplate().update("update MY_TABLE set BLOB_COLUMN = ? where ROWID = '1'", bytes);
READ:
we can either read blob from database in Blob class or transform into String. To transform it into String we will need additional custom method:
public static String sqlBlobToString(Blob blob) {
StringBuilder stringBuilder = new StringBuilder();
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(blob.getBinaryStream())) {
while ((string = bufferedReader.readLine()) != null) {
stringBuilder.append(string);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return stringBuilder;
}
Querying from database:
String s = sqlBlobToString(getJdbcTemplate().queryForObject("select BLOB_COLUMN from MY_TABLE where ROWID = '1'", Blob.class));
Note: I am using java.sql.Blob
To transform String value into blob just execute your_string.getBytes();
String blobValue = "long blob";
bytes[] bytes = blobValue.getBytes();
int rows = getJdbcTemplate().update("update MY_TABLE set BLOB_COLUMN = ? where ROWID = '1'", bytes);
READ:
we can either read blob from database in Blob class or transform into String. To transform it into String we will need additional custom method:
public static String sqlBlobToString(Blob blob) {
StringBuilder stringBuilder = new StringBuilder();
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(blob.getBinaryStream())) {
while ((string = bufferedReader.readLine()) != null) {
stringBuilder.append(string);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return stringBuilder;
}
Querying from database:
String s = sqlBlobToString(getJdbcTemplate().queryForObject("select BLOB_COLUMN from MY_TABLE where ROWID = '1'", Blob.class));
Note: I am using java.sql.Blob
How to write / read CLOB to / from Oracle database?
WRITE:
there is no problems with clob saving into db - just keep it in String value and regularly save it:
String clobValue = "long clob";
int rows = getJdbcTemplate().update("update MY_TABLE set CLOB_COLUMN = ? where ROWID = '1'", clobValue);
READ:
we can either read clob from database in Clob class or transform into String. To transform it into String we will need additional custom method:
public static String sqlClobToString(Clob clob) {
StringBuilder stringBuilder = new StringBuilder();
try(BufferedReader bufferedReader = new BufferedReader(clob.getCharacterStream()) {
while ((string = bufferedReader.readLine()) != null) {
stringBuilder.append(string);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return stringBuilder;
}
Querying from database:
String s = sqlClobToString(getJdbcTemplate().queryForObject("select CLOB_COLUMN from MY_TABLE where ROWID = '1'", Clob.class));
Note: I am using java.sql.Clob
there is no problems with clob saving into db - just keep it in String value and regularly save it:
String clobValue = "long clob";
int rows = getJdbcTemplate().update("update MY_TABLE set CLOB_COLUMN = ? where ROWID = '1'", clobValue);
READ:
we can either read clob from database in Clob class or transform into String. To transform it into String we will need additional custom method:
public static String sqlClobToString(Clob clob) {
StringBuilder stringBuilder = new StringBuilder();
try(BufferedReader bufferedReader = new BufferedReader(clob.getCharacterStream()) {
while ((string = bufferedReader.readLine()) != null) {
stringBuilder.append(string);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return stringBuilder;
}
Querying from database:
String s = sqlClobToString(getJdbcTemplate().queryForObject("select CLOB_COLUMN from MY_TABLE where ROWID = '1'", Clob.class));
Note: I am using java.sql.Clob
Thursday, 2 July 2015
How to switch to debug mode without application re-deploy in Intellij Idea for Weblogic?
1. Open file in Notepad
../{your_weblogic_folder}/user_projects/domains/{your_domain_name}/bin/setDomainEnv.cmd
2. Set the following value for JAVA_DEBUG variable, line will look this way:
set JAVA_DEBUG=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=50000,server=y,suspend=n
where 50000 is any port number you wish to use for debug.
3. In Intellij Idea Run -> Edit Configuration ->click + and add 'Remote' configuration.
4. Configure Remote configuration: add 'Name', set 'Port' number, the same you have indicated in point 2.
Run application in regular mode and when needed switch to debug.
../{your_weblogic_folder}/user_projects/domains/{your_domain_name}/bin/setDomainEnv.cmd
2. Set the following value for JAVA_DEBUG variable, line will look this way:
set JAVA_DEBUG=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=50000,server=y,suspend=n
where 50000 is any port number you wish to use for debug.
3. In Intellij Idea Run -> Edit Configuration ->click + and add 'Remote' configuration.
4. Configure Remote configuration: add 'Name', set 'Port' number, the same you have indicated in point 2.
Run application in regular mode and when needed switch to debug.
Wednesday, 1 July 2015
How to start / stop weblogic manually?
START: Run ../user_projects/domains/your_domain_name/startWeblogic.cmd
or ../user_projects/domains/your_domain_name/bin/startWeblogic.cmd
STOP: Run ../user_projects/domains/your_domain_name/bin/stopWeblogic.cmd
or ../user_projects/domains/your_domain_name/bin/startWeblogic.cmd
STOP: Run ../user_projects/domains/your_domain_name/bin/stopWeblogic.cmd
How to create domain in weblogic?
1. Run ../oracle_common/common/bin/config.cmd
2. Configuration Wizard will open
3. CREATE DOMAIN: Choose "Create new domain" option and specify desired domain location with domain name in the end.
(Ex: C:\Users\arina\user_projects\domains\base_domain, where base_domain is our new domain name)
4. TEMPLATES: Leave as it is and click Next.
5. ADMINISTRATOR ACCOUNT: Enter administrator credentials and click Next
6. DOMAIN MODE and JDK: I choose Development for Domain Mode, and leave embedded Weblogic JDK, and click Next
7. ADVANCED CONFIGURATIONS: Mostly I usually need only Administration Server, chose it and click Next
8. ADMINISTRATION SERVER: Usually I leave Server Name as is "AdminServer" but it's optional. Listen port: specify which port you want weblogic to use, let's say 7171, 9191 or any you like, and click Next.
9. CONFIGURATION SUMMARY: review your configurations and click Create
10. After progress bar reached 100% and Next button activated, click Next.
11. Review Domain Location, Admin Server URL, if you need to start Start Admin Server right away select appropriate checkbox and click Finish.
2. Configuration Wizard will open
3. CREATE DOMAIN: Choose "Create new domain" option and specify desired domain location with domain name in the end.
(Ex: C:\Users\arina\user_projects\domains\base_domain, where base_domain is our new domain name)
4. TEMPLATES: Leave as it is and click Next.
5. ADMINISTRATOR ACCOUNT: Enter administrator credentials and click Next
6. DOMAIN MODE and JDK: I choose Development for Domain Mode, and leave embedded Weblogic JDK, and click Next
7. ADVANCED CONFIGURATIONS: Mostly I usually need only Administration Server, chose it and click Next
8. ADMINISTRATION SERVER: Usually I leave Server Name as is "AdminServer" but it's optional. Listen port: specify which port you want weblogic to use, let's say 7171, 9191 or any you like, and click Next.
9. CONFIGURATION SUMMARY: review your configurations and click Create
10. After progress bar reached 100% and Next button activated, click Next.
11. Review Domain Location, Admin Server URL, if you need to start Start Admin Server right away select appropriate checkbox and click Finish.
How to clone specific branch in git?
If git repository is too big and you can't clone (or don't want to) all of it, you can clone specific branch:
git clone -b [branch_name] --single-branch http://arina.git
git clone -b [branch_name] --single-branch http://arina.git
Monday, 22 June 2015
How to personalize file header in Intellij Idea?
1. Press Ctrl+Alt+S
2. Look for File and Code templates
3. In Includes tab chose File Header
4. Add:
/**
* @author Arina Ielchiieva
* Date: ${DATE}
* Time: ${TIME}
*/
2. Look for File and Code templates
3. In Includes tab chose File Header
4. Add:
/**
* @author Arina Ielchiieva
* Date: ${DATE}
* Time: ${TIME}
*/
Friday, 19 June 2015
Class < ? > vs Class usage
Class // An unknown class (raw type)
Class<?> // An unknown class (generic version)
Class<String> // The String class
Since Java 1.5 you should use the generic form wherever possible.
Class
Class<?> // An unknown class (generic version)
Class<String> // The String class
Since Java 1.5 you should use the generic form wherever possible.
Class<?>
clearly states that you mean "an unknown class".Class
<?>
shows that you're intentionally writing Java 5-level code that doesn't know or care what class you are dealing with. Leaving out the makes it look like old code or code written by someone who hasn't learned generics yet.
How to view detailed information about Intellij Idea warnings?
Press Alt+Ctrl+S
Search for "Java Compiler"
In "Additional command line parameters:" type the following:-Xlint:unchecked
and recompile class again.
Search for "Java Compiler"
In "Additional command line parameters:" type the following:-Xlint:unchecked
and recompile class again.
How To Acсess Target Object Behind a Spring Proxy?
If you have @Autowired spring bean but for some reason (preferably for unit testing purposes in order to stub something) you want to get target object behind Spring proxy:
((Advised)yourAutowiredBean).getTargetSource().getTarget();
AopUtils.isJdkDynamicProxy(yourAutowiredBean) - can confirm you got proxied object if you have any doubts.
((Advised)yourAutowiredBean).getTargetSource().getTarget();
AopUtils.isJdkDynamicProxy(yourAutowiredBean) - can confirm you got proxied object if you have any doubts.
Wednesday, 17 June 2015
Which pid is using your port?
Show which pid uses your port:
netstat -a -n -o | find "your_port [ex: 9191]"
To kill pid from console: taskkill /pid pid_number
netstat -a -n -o | find "your_port [ex: 9191]"
To kill pid from console: taskkill /pid pid_number
Good DataSource
DriverManagerDataSource by Spring can act weird sometimes, so the best choice to use Apache data source: BasicDataSource.
Configuration:
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(JDBC_URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
dataSource.setDriverClassName(DRIVER_CLASS_NAME);
}
Maven:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1</version>
</dependency>
How to match any enum?
Matchers.any(MyEnum.class):
when(serviceMock.preview(anyString(), any(DataSourceEnum.class)).thenReturn(anyMapOf(String.class, Collection.class)
when(serviceMock.preview(anyString(), any(DataSourceEnum.class)).thenReturn(anyMapOf(String.class, Collection.class)
Subscribe to:
Posts (Atom)