Friday, April 8, 2016

Spring Misc Part 2



http://websystique.com/springmvc/spring-mvc-requestbody-responsebody-example/
@RequestBody @ResponseBody

Spring mvc - jsonview
http://javaworkbench.blogspot.com/2013/04/spring-mvc-jackson-and-filtering-json.html

http://vard-lokkur.blogspot.co.uk/2010/10/json-jackson-serialization-narrowed.html
        objectMapper.getSerializationConfig().setSerializationView(Employer.PublicView.class);

        objectMapper.getSerializationConfig().setSerializationView(Employer.PublicView.class);
        view.setObjectMapper(objectMapper);
        view.setRenderedAttributes(new HashSet(Arrays.asList(MODEL_KEY_EMPLOYEES)));
    }

    @RequestMapping(method = RequestMethod.GET)
    public View handleGet(@RequestParam("employerId") Long employerId, Model model) {
        model.addAttribute(MODEL_KEY_EMPLOYEES, employerDAO.getEmployees(employerId));
        return view;
    }
http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html
    private final ObjectMapper objectMapper = new ObjectMapper();

    private final MappingJacksonJsonView view = new MappingJacksonJsonView();      
    
    public SearchController() {         
        objectMapper.getSerializationConfig().addMixInAnnotations(Collector.class, CollectorIdOnlyView.class);
        view.setObjectMapper(objectMapper);
          
    }
    @Autowired
    private AccountService accountService;
      
    @Autowired
    private SearchService searchService;
      
    @RequestMapping(value = "/search/{id}", method = RequestMethod.GET)
    public View getSummary(@PathVariable("id") String id, Model uiModel) {
        Collector collector = accountService.findCollectorById(id);
        if(collector == null) {
              throw new RuntimeException("Collector Not Found");
        } else {
              SearchSummary searchSummary = searchService.getSearchSummary(collector);
              uiModel.addAttribute("summary",searchSummary);
              return view;
        }
       
    }

https://github.com/eugenp/tutorials/blob/master/spring-data-cassandra
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java
@Bean
@ConditionalOnMissingBean
public CassandraTemplate cassandraTemplate(Session session,
    CassandraConverter converter) throws Exception {
  return new CassandraTemplate(session, converter);
}
http://howtodoinjava.com/spring/spring-core/how-to-use-spring-component-repository-service-and-controller-annotations/
@Component, @Repository, @Service and @Controller annotations
2) Although above use of @Component is good enough but you can use more suitable annotation that provides additional benefits specifically for DAOs i.e. @Repository annotation. The @Repository annotation is a specialization of the @Component annotation with similar use and functionality. In addition to importing the DAOs into the DI container, it also makes the unchecked exceptions (thrown from DAO methods) eligible for translation into Spring DataAccessException.
hen you add the @Controller annotation to a class, you can use another annotation i.e. @RequestMapping; to map URLs to instance methods of a class.
http://stackoverflow.com/questions/30691949/how-to-inject-a-map-using-the-value-spring-annotation
You can inject values into a Map from the properties file using the @Value annotation like this.
The property in the properties file.
propertyname={key1:'value1',key2:'value2',....}
In your code.
@Value("#{${propertyname}}")  private Map<String,String> propertyname;

I believe Spring Boot supports loading properties maps out of the box with @ConfigurationProperties annotation.

According that docs you can load properties:

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

into bean like this:
@ConfigurationProperties(prefix="my")
public class Config {

    private List<String> servers = new ArrayList<String>();

    public List<String> getServers() {
        return this.servers;
    }
}
How spring autowire list, map
http://stackoverflow.com/questions/13948921/can-create-hashmap-with-spring-but-cant-create-map

While declaring a bean of type collection, one cannot inject it via @Autowired. See below documentation from Spring:
As a specific consequence of this semantic difference, beans which are themselves defined as a collection or map type cannot be injected via @Autowired since type matching is not properly applicable to them. Use @Resource for such beans, referring to the specific collection/map bean by unique name.
Thus instead of @Autowired, use @Resource:
@Resource
@Qualifier("map")
private Map<String, String> map;
http://www.nurkiewicz.com/2015/04/spring-injecting-lists-maps-optionals.html
Suppose you have more than one bean implementing a given interface. Trying to autowire just one bean of such interface is doomed to fail because Spring has no idea which particular instance you need. You can work around that by using @Primary annotation to designate exactly one "most important" implementation that will have priority over others

Auto-discovering all implementations at runtime is a fantastic illustration of Open/closed principle: you can easily add new behavior to business logic (validators, algorithms, strategies - open for extension) without touching the business logic itself (closed for modification). 

    @Autowired
    List<StringCallable> list;
    @Autowired
    Set<StringCallable> set;
    @Autowired
    Map<String, StringCallable> map;

http://www.concretepage.com/spring/example_threadpooltaskexecutor_spring
It's somewhat controversial, but often this wrapper implements the same interface as well, effectively implementing composite classic design pattern:

@Component
@Primary
public class Caller implements StringCallable {
    private final List<StringCallable> callables;
    @Autowired
    public Caller(List<StringCallable> callables) {
        this.callables = callables;
    }
    @Override
    public String call() {
        return callables.stream()
                .map(StringCallable::call)
                .collect(joining("|"));
    }
}
Interestingly there is another solution that goes straight to Spring guts: ListableBeanFactory.getBeansOfType():

callables = new ArrayList<>(beanFactory.getBeansOfType(StringCallable.class).values());

Problem solved? Quite the opposite! getBeansOfType() will silently skip (well, there is TRACE and DEBUG log...) beans under creation and only returns those already existing. Therefor Caller was just created and container started successfully, while it no longer references Fifth bean. You might say I asked for it because we have a circular dependency so weird things happens. But it's an inherent feature of getBeansOfType(). In order to understand why using getBeansOfType() during container startup is a bad idea,

getBeansOfType() is rarely needed and turns out to be unpredictable if you have cyclic dependencies.
http://shmilyaw-hotmail-com.iteye.com/blog/2169156
    这种模型是怎么保证系统的高可用性和性能的呢?在这里,因为每个节点都执行不同的job,我们必须保证对于给定的任务只是在单独的一个节点上执行。所以当cluster里最先能够抢占到该任务的节点执行的时候,它会对数据库里对应这个任务的行加锁,然后后续的就不能再去占用了。通过利用锁的机制,这里也比较容易实现一个负载均衡,每次节点只要去取到那些没有被加锁的任务执行就可以了。关于quartz的内部执行细节会在后续的文章里描述。
   很明显,如果要在一个集群的模式下设置多个节点,每个节点必然会执行一到多个任务。这些任务的分配和执行情况需要记录和跟踪。同时怎么来调度资源协调它们也是一个需要考虑的问题。好在quartz里面已经提供了一些默认的配置支持,比如线程池和数据库连接池。一个典型的示例配置如下:
http://forums.terracotta.org/forums/posts/list/5212.page
https://www.javacodegeeks.com/2014/05/how-to-quartz-scheduler-with-clustering-in-jee-application-with-mysql.html
https://github.com/elventear/quartz-scheduler/blob/master/distribution/src/main/assembly/root/docs/dbTables/tables_mysql.sql
https://objectpartners.com/2013/07/09/configuring-quartz-2-with-spring-in-clustered-mode/
http://flylib.com/books/en/2.65.1.92/1/

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html
http://www.quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigJDBCJobStoreClustering.html
Clustering currently only works with the JDBC-Jobstore (JobStoreTX or JobStoreCMT), and essentially works by having each node of the cluster share the same database.
Load-balancing occurs automatically, with each node of the cluster firing jobs as quickly as it can. When a trigger’s firing time occurs, the first node to acquire it (by placing a lock on it) is the node that will fire it.
Only one node will fire the job for each firing. What I mean by that is, if the job has a repeating trigger that tells it to fire every 10 seconds, then at 12:00:00 exactly one node will run the job, and at 12:00:10 exactly one node will run the job, etc. It won’t necessarily be the same node each time - it will more or less be random which node runs it. The load balancing mechanism is near-random for busy schedulers (lots of triggers) but favors the same node for non-busy (e.g. few triggers) schedulers.

http://khalidsaleem.blogspot.com/2015/03/quartz-scheduler-vs-spring-scheduler.html
On the contrary, Quartz Scheduler is a full fledged open source library that provides support for Job Scheduling. Its comparatively complex than Spring Scheduler but provides support for enterprise level features like JTA and clustering. It comes with JobPersistence support that can be extremely beneficial for failed jobs as well as reporting purposes.
  • With the use of the included JDBCJobStore, all Jobs and Triggers configured as "non-volatile" are stored in a relational database via JDBC.
  • With the use of the included RAMJobStore, all Jobs and Triggers are stored in RAM and therefore do not persist between program executions - but this has the advantage of not requiring an external database. 

http://stackoverflow.com/questions/2147958/how-do-i-prevent-people-from-doing-xss-in-spring-mvc
In Spring you can escape the html from JSP pages generated by <form> tags. This closes off a lot avenues for XSS attacks, and can be done automatically in three ways:
For the entire application in the web.xml file:
<context-param>
    <param-name>defaultHtmlEscape</param-name>
    <param-value>true</param-value>
</context-param>
For all forms on a given page in the file itself:
<spring:htmlEscape defaultHtmlEscape="true" /> 
For each form:
<form:input path="someFormField" htmlEscape="true" /> 

http://stackoverflow.com/questions/1199358/how-to-get-the-id-of-a-bean-from-inside-the-bean-in-spring
Just implement the org.springframework.beans.factory.BeanNameAware interface and you will get it automatically. It has one method:
void setBeanName(String name)
http://www.kubrynski.com/2014/01/understanding-spring-web-initialization.html
Java EE provides ServletContainerInitializer interface, which allows libraries to be notified of a web application startup. SinceSpring 3.1 we have SpringServletContainerInitializer class which handles WebApplicationInitializer by instantiating all found classes implementing this interface, sorting them basing on @Order annotation (non-annotated classes gets the highest possible order, so they are processed at the end) and invoking onStartup() method.
Java EE provides ServletContainerInitializer interface, which allows libraries to be notified of a web application startup. SinceSpring 3.1 we have SpringServletContainerInitializer class which handles WebApplicationInitializer by instantiating all found classes implementing this interface, sorting them basing on @Order annotation (non-annotated classes gets the highest possible order, so they are processed at the end) and invoking onStartup() method.

Spring since version 3.2 provides us a few classes implementing WebApplicationInitializer interface, from which first isAbstractContextLoaderInitializer. This class included in spring-web module uses abstract createRootApplicationContext()method to create application context, delegates it to ContextLoaderListener which then is being registered in theServletContext instance. Creating application context using this class looks as follows:
1
2
3
4
5
6
7
8
9
10
11
12
public class SpringAnnotationWebInitializer
  extends AbstractContextLoaderInitializer {
  @Override
  protected WebApplicationContext createRootApplicationContext() {
    AnnotationConfigWebApplicationContext applicationContext =
      new AnnotationConfigWebApplicationContext();
    applicationContext.register(SpringAnnotationConfig.class);
    return applicationContext;
  }
}

That was the simplest way to start up Spring web context. But if we want to experience benefits provided by Spring MVC and don't want to manually register DispatcherServlet it'll be better to use another class: AbstractDispatcherServletInitializer. It extends previous class and adds two abstract methods: createServletApplicationContext() and getServletMappings().  First method returns WebApplicationContext that will be passed to DispatcherServlet, which will be automatically added into container ServletContext. Please notice that this context will be established as a child of the context returned by createRootApplicationContext() method. Second method - as you have probably already deduced - returns mappings that are used during servlet registration. You can also override getServletFilters() method if you need any custom filters, because default implementation returns just empty array. Exemplary implementation using this class could be:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SpringWebMvcInitializer
  extends AbstractDispatcherServletInitializer {
  @Override
  protected WebApplicationContext createRootApplicationContext() {
    AnnotationConfigWebApplicationContext applicationContext =
      new AnnotationConfigWebApplicationContext();
    applicationContext.register(SpringRootConfig.class);
    return applicationContext;
  }
  @Override
  protected WebApplicationContext createServletApplicationContext() {
    AnnotationConfigWebApplicationContext applicationContext =
      new AnnotationConfigWebApplicationContext();
    applicationContext.register(SpringMvcConfig.class);
    return applicationContext;
  }
  @Override
  protected String[] getServletMappings() {
    return new String[]{"/*"};
  }
}

And now last but definitely not least class: AbstractAnnotationConfigDispatcherServletInitializer. Here we can see further step in simplifying Spring initialization - we don't need to manually create contexts but just set appropriate config classes in getRootConfigClasses() and getServletConfigClasses() methods. I hope you are already familiar with those names, because they works exactly like in the former case. Of course due to this class extends AbstractDispatcherServletInitializer we can still override getServletFilters(). Finally we can implement our configuration in the following way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class SpringWebMvcSimpleInitializer
  extends AbstractAnnotationConfigDispatcherServletInitializer {
  @Override
  protected Class<?>[] getRootConfigClasses() {
    return new Class[] {SpringRootConfig.class};
  }
  @Override
  protected Class<?>[] getServletConfigClasses() {
    return new Class[] {SpringMvcConfig.class};
  }
  @Override
  protected String[] getServletMappings() {
    return new String[]{"/*"};
  }
}

http://stackoverflow.com/questions/11708967/what-is-the-difference-between-applicationcontext-and-webapplicationcontext-in-s
Web Application context extended Application Context which is designed to work with the standardjavax.servlet.ServletContext so it's able to communicate with the container.
public interface WebApplicationContext extends ApplicationContext {
    ServletContext getServletContext();
}
Beans, instantiated in WebApplicationContext will also be able to use ServletContext if they implement ServletContextAware interface
package org.springframework.web.context;
public interface ServletContextAware extends Aware { 
     void setServletContext(ServletContext servletContext);
}
There are many things possible to do with the ServletContext instance, for example accessing WEB-INF resources(xml configs and etc.) by calling the getResourceAsStream() method. Typically all application contexts defined in web.xml in a servlet Spring application are Web Application contexts, this goes both to the root webapp context and the servlet's app context.
Also, depending on web application context capabilities may make your application a little harder to test, and you may need to use MockServletContext class for testing.
Difference between servlet and root context Spring allows you to build multilevel application context hierarchies, so the required bean will be fetched from the parent context if it's not present in the current application context. In web apps as default there are two hierarchy levels, root and servlet contexts:enter image description here
This allows you to run some services as the singletons for the entire application (Spring Security beans and basic database access services typically reside here) and another as separated services in the corresponding servlets to avoid name clashes between beans. For example one servlet context will be serving the web pages and another will be implementing a stateless web service.
This two level separation comes out of the box when you use the spring servlet classes: to configure the root application context you should use context-param tag in your web.xml
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/root-context.xml
            /WEB-INF/applicationContext-security.xml
    </param-value>
</context-param>
(the root application context is created by ContextLoaderListener which is declared in web.xml
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener> 
ApplicationContext applicationContext.xml is the root context configuration for every web application. Spring loads applicationContext.xml file and creates the ApplicationContext for the whole application. There will be only one application context per web application. If you are not explicitly declaring the context configuration file name in web.xml using the contextConfigLocation param, Spring will search for the applicationContext.xml under WEB-INF folder and throw FileNotFoundException if it could not find this file.
WebApplicationContext Apart from ApplicationContext, there can be multiple WebApplicationContext in a single web application. In simple words, each DispatcherServlet associated with single WebApplicationContext. xxx-servlet.xml file is specific to the DispatcherServlet and a web application can have more than one DispatcherServlet configured to handle the requests. In such scenrios, each DispatcherServlet would have a separate xxx-servlet.xml configured. But, applicationContext.xml will be common for all the servlet configuration files. Spring will by default load file named “xxx-servlet.xml” from your webapps WEB-INF folder where xxx is the servlet name in web.xml. If you want to change the name of that file name or change the location, add initi-param with contextConfigLocation as param name.
) and servlet tag for the servlet application contexts
<servlet>
   <servlet-name>myservlet</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>app-servlet.xml</param-value>
   </init-param>
</servlet>
http://stackoverflow.com/questions/12537851/accessing-spring-beans-in-static-class
My approach is for the bean one wishes to access to implement InitializingBean or use @PostConstruct, and containing a static reference to itself.
@Service
public class MyBean implements InitializingBean {
    private static MyBean instance;

    @Override
    public void afterPropertiesSet() throws Exception {
        instance = this;
    }

    public static MyBean get() {
        return instance;
    }
}

https://www.mkyong.com/spring-mvc/spring-mvc-how-to-set-active-profile/
ublic class MyWebInitializer extends
 AbstractAnnotationConfigDispatcherServletInitializer {

 //If the @Profile beans are loaded via root context
 @Override
 protected WebApplicationContext createRootApplicationContext() {

  WebApplicationContext context =
                     (WebApplicationContext)super.createRootApplicationContext();
      ((ConfigurableEnvironment)context.getEnvironment()).setActiveProfiles("live");

  //Set multiple active profiles
  //((ConfigurableEnvironment)context.getEnvironment())
                //          .setActiveProfiles(new String[]{"live", "testdb"});

      return context;

 }
http://stackoverflow.com/questions/12383671/ordering-listeners-in-springs-webapplicationinitializer
I just realized while debugging this that manually instantiating the object doesn't allow Spring to autowire it, as you said
http://www.leveluplunch.com/blog/2014/04/01/spring-boot-configure-servlet-mapping-filters/
http://stackoverflow.com/questions/12537851/accessing-spring-beans-in-static-class
My approach is for the bean one wishes to access to implement InitializingBean or use @PostConstruct, and containing a static reference to itself.
@Service
public class MyBean implements InitializingBean {
    private static MyBean instance;

    @Override
    public void afterPropertiesSet() throws Exception {
        instance = this;
    }

    public static MyBean get() {
        return instance;
    }
}
http://tuhrig.de/making-a-spring-bean-session-scoped/
The value of @Scope can be one of singleton (one single instance for the whole app), prototype (a new instance for every injection), request (an instance per web request) or session (an instance per web session). See here.
The last two scopes (request and session) are only available in Spring web applications where the current session is exposed. To do so, you need to add a listener to the web.xml which makes the context available:
To solve this problem, Spring provides a proxy mechanism. This means Spring can wire a proxy with the same interface as your actual bean instead of the bean itself. The proxy will not be session scoped (it will be a singleton), but it will fetch the according session scoped bean for each request. This means you can wire your session scoped bean in a not session scoped service and the proxy will do the rest behind the scenes.
To use such a proxy, you can just add it to the @Scope annotation like that:
If you do so, you will discover the next problem soon: what about your integration tests you made which probably will fail now as they got no session? The easiest fix for this, is to add the following bean configuration, which adds a session context for each thread (see the post of Tarun Sapra for the original description):


http://stackoverflow.com/questions/29413290/how-exactly-works-the-spring-session-scope-of-a-bean-what-is-the-default-scope
Actually Spring help you create Session scope bean instead traditional way
httpSession.setAttribute("Object",new Object());
&&
httpSession.getAttribute("Object");
and Spring provide this efficient way
@Component
@Scope("session")
public class Foo{
}
now it's headache of spring to create and destroy this associated session object using Factory Pattern
http://springinpractice.com/2008/05/08/session-scoped-beans-in-spring
http://richardchesterwood.blogspot.com/2011/03/using-sessions-in-spring-mvc-including.html
Cons: it's messy, exposes your clean controller to the Servlet API and needs null checking after you've called getAttribute. Unit testing of your controller is now much harder to do (you need to Mock the HttpSession object).
2: Scope the Controller
Cons: A new controller is created for each session, the controller object must be stored in HttpSession. This could bloat the session and in particular could mean replication problems on a large scale system. (Replication: where your web application is hosted on multiple servers. Then the session has to be copied from one server to another. Whilst this is automatic, big sessions cause serious performance problems)

@Component
@Scope("session")
public class ShoppingCart
{
   // just a plain java class - member variables and methods as usual
}
   @Autowired
   private ShoppingCart cart;

spring can not set to com.sun.proxy.$proxy
http://stackoverflow.com/questions/18369258/spring-aop-at-service-layer
@samlewis: This sentence that you wrote pushed me to create interfaces to my Services and when I did that, LoggingAspect worked really fine. So, I'm not using proxy-target-class=true.
You are not injecting an interface so you need to use CGLIB proxies, the spring reference manualstates:
Spring AOP defaults to using standard J2SE dynamic proxies for AOP proxies. This enables any interface (or set of interfaces) to be proxied.
Spring AOP can also use CGLIB proxies. This is necessary to proxy classes, rather than interfaces. CGLIB is used by default if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes, business classes normally will implement one or more business interfaces.
Spring has decided to use a J2SE proxy (com.sun.proxy.$Proxy57) probably because CrudService implements an interface. To force the use of CGLIB you can tweak your XML:
<aop:aspectj-autoproxy proxy-target-class="true"/>
-- If your class implements some interfaces, the it has to be injected using that interface.

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#aop-proxying
  • final methods cannot be advised, as they cannot be overridden.
  • As of Spring 3.2, it is no longer necessary to add CGLIB to your project classpath, as CGLIB classes are repackaged under org.springframework and included directly in the spring-core JAR. This means that CGLIB-based proxy support 'just works' in the same way that JDK dynamic proxies always have.
Spring

http://stackoverflow.com/questions/12576156/reading-a-list-from-properties-file-and-load-with-spring-annotation-value
Using Spring EL:
 @Value("#{'${my.list.of.strings}'.split(',')}") 
 private List<String> myList;

@Bean public ConversionService conversionService() { //
    return new DefaultConversionService();
}
@Value("${my.list.of.ints}")
private List<Integer> myList
will work with a line like
 my.list.of.ints= 1, 2, 3, 4
Spring properties
-empty string can't be converted to boolean.
Failed to convert value of type 'java.lang.String' to required type 'boolean';
http://joshlong.com/jl/blogPost/simplified_web_configuration_with_spring.html
public class CrmWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    private int maxUploadSizeInMb = 5 * 1024 * 1024; // 5 MB

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{ServiceConfiguration.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{RepositoryRestMvcConfiguration.class, WebMvcConfiguration.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[]{new HiddenHttpMethodFilter(), new MultipartFilter(), new OpenEntityManagerInViewFilter()};
    }

    @Override
    protected void registerDispatcherServlet(ServletContext servletContext) {
        super.registerDispatcherServlet(servletContext);

        servletContext.addListener(new HttpSessionEventPublisher());

    }

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {

        File uploadDirectory = ServiceConfiguration.CRM_STORAGE_UPLOADS_DIRECTORY;

        MultipartConfigElement multipartConfigElement = 
            new MultipartConfigElement(uploadDirectory.getAbsolutePath(),
                maxUploadSizeInMb, maxUploadSizeInMb * 2, maxUploadSizeInMb / 2);

        registration.setMultipartConfig(multipartConfigElement);

    }
}
http://sleeplessinslc.blogspot.com/2014/04/jerseyjaxrs-2x-example-using-spring.html

http://stackoverflow.com/questions/938926/ehcache-multithreading
From the official documentation appears it is specifically built and tested to run well under highly concurrent access, as long as you do not modify Element from the multiple threads.
But, of course, this does not mean that using Ehcache makes other parts of your code thread safe. If you fetch the same value from multiple threads (using the same key), the instance may be shared and you need to know what you are doing before modifying it. Best seems to use immutable objects like strings as cached values.
Is it thread safe to modify Element values after retrieval from a Cache?
Remember that a value in a cache element is globally accessible from multiple threads. It is inherently not thread safe to modify the value. It is safer to retrieve a value, delete the cache element and then reinsert the value.

http://www.journaldev.com/2637/spring-bean-life-cycle
An ApplicationContext automatically detects any beans that are defined with implementation of the BeanPostProcessor interface and registers these beans as post-processors, to be then called appropriately by the container upon bean creation.
Scheduler
https://darthanthony.wordpress.com/2009/07/07/dynamic-scheduling-with-javaspring/
If you are wanting to dynamically create scheduled tasks you cannot rely on XML configuration.  Instead we will use a programmatic process to do a similar thing that happens with the configuration example above.  The general process is:
  1. Wire up a SchedulerFactoryBean as above.  We will use this bean wired Spring service to create our schedules with.
  2. In your code either inject the scheduler factory or access it using the Spring application context.
  3. Get access to an instance of the object that will be executed on the timed basis.
  4. Create an instance of a MethodInvokingJobDetailFactoryBean (thats a mouthful).  This object is a wrapper for a job object (that will get linked to a trigger) for execution.
  5. Create an instance of a SimpleTriggerBean (for simple interval triggers) or a CronTriggerBean (for CRON based triggers).
  6. Schedule the job with the scheduler.
//get the quartzFactory bean
Scheduler scheduler = (Scheduler) ctx.getBean("scheduleFactory");

//get the task to run or it could have been injected
DataPollingTask dpTask = (DataPollingTask) ctx.getBean(taskName);

//this example uses a simple interval schedule, but could be done with a CRON schedule by using the correct Trigger Bean (CronTriggerBean)
//create job
jobDetail = new MethodInvokingJobDetailFactoryBean();
jobDetail.setTargetObject(dpTask);
jobDetail.setTargetMethod("run");
jobDetail.setName(taskName);
jobDetail.setConcurrent(false);
jobDetail.afterPropertiesSet();

//create trigger
SimpleTriggerBean trigger = new SimpleTriggerBean();
trigger.setBeanName(taskName);
trigger.setJobDetail((JobDetail) jobDetail.getObject());
trigger.setRepeatInterval(interval);
trigger.afterPropertiesSet();

//add to schedule
scheduler.scheduleJob((JobDetail) jobDetail.getObject(), trigger);

https://discuss.zendesk.com/hc/en-us/articles/202653068-Registering-unregistering-scheduling-and-unscheduling-Task-Scheduler-at-runtime-in-Spring-Framework-3-0-3-1-2010476-
public class TaskManager {

    @Autowired
    private StdSchedulerFactory schedulerFactory;

public void manageTasks(){
        try {
         
            //gets a reference from Quartz Scheduler
            scheduler = (StdScheduler) this.schedulerFactory.getScheduler();
         
         
            //manage jobs using Quartz API
            JobDetail job = JobBuilder.newJob(MyJob.class)
                      .withIdentity("myJob", "group1")
                      .build();

            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("myTrigger", "group1")
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(40)
                            .repeatForever())        
                            .build();
         
            // add Job
            scheduler.addJob(job, true);
            // define a schedule
            scheduler.scheduleJob(job, trigger);
         
         
            scheduler.start();
            // pause Job
            scheduler.pauseJob(job.getKey());
         
         
            scheduler.unscheduleJob(trigger.getKey());
            scheduler.deleteJob(job.getKey());
         
            scheduler.shutdown();

 

        } catch (SchedulerException e){
            e.printStackTrace();
        }
    }

}
http://feed.hjue.me/articles/detail/2015-10-19/651934/string-xml-ca
我们今天先看默认mode=proxy的情况,进入方法,发现方法里面注册了三个Bean到Context里面,分别是CacheOperationSource、CacheInterceptor和BeanFactoryCacheOperationSourceAdvisor。
熟悉AOP原理的看到Interceptor和Advisor一般都会明白大半了,并且他们共同都有一个属性cacheOperationSources,实现类是org.springframework.cache.annotation.AnnotationCacheOperationSource。
下面我们先来喵两眼这两个类,先看BeanFactoryCacheOperationSourceAdvisor,里面有一个叫CacheOperationSourcePointcut的pointcut,用来匹配方法是否需要走拦截器。通过调用之前注入进去的cacheOperationSources.getCacheOperations获取CacheOperation,代码如下:
@Cacheable(cacheNames="book", condition="#name.length < 32", unless="#result.hardback")
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html
ThreadPoolExecutor that can additionally schedule commands to run after a given delay, or to execute periodically. This class is preferable to Timer when multiple worker threads are needed, or when the additional flexibility or capabilities ofThreadPoolExecutor (which this class extends) are required.
Delayed tasks execute no sooner than they are enabled, but without any real-time guarantees about when, after they are enabled, they will commence. Tasks scheduled for exactly the same execution time are enabled in first-in-first-out (FIFO) order of submission.
When a submitted task is cancelled before it is run, execution is suppressed. By default, such a cancelled task is not automatically removed from the work queue until its delay elapses. While this enables further inspection and monitoring, it may also cause unbounded retention of cancelled tasks. To avoid this, set setRemoveOnCancelPolicy(boolean) to true, which causes tasks to be immediately removed from the work queue at time of cancellation.
Successive executions of a task scheduled via scheduleAtFixedRate or scheduleWithFixedDelay do not overlap. While different executions may be performed by different threads, the effects of prior executions happen-before those of subsequent ones.
While this class inherits from ThreadPoolExecutor, a few of the inherited tuning methods are not useful for it. In particular, because it acts as a fixed-sized pool using corePoolSize threads and an unbounded queue, adjustments to maximumPoolSize have no useful effect. Additionally, it is almost never a good idea to set corePoolSize to zero or use allowCoreThreadTimeOut because this may leave the pool without threads to handle tasks once they become eligible to run.

Event:
https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2

Spring之ContextLoaderListener的作用
http://blog.csdn.net/c5153000/article/details/6234207

http://stackoverflow.com/questions/29664785/spring-contextloaderlistener-role-in-bean-creation
  • The idea behind the ApplicationContext in Spring is that in order to properly inject objects where they are needed, some thing needs to be aware of the configuration the user specifies and inject dependencies based on this configuration.
  • The ApplicationContext is the thing that understands the user's wishes in terms of where and what should be injected (as well as other things such as AOP pointcuts and such) based on the configuration a user provides, either through an xml file or annotations.
  • The context named after your servlet ( [servlet-name]-context.xml ) is aWebApplicationContext and is a child context of the main ApplicationContext, which is created from the files listed in the contextConfigLocation and loaded by the ContextLoaderListener. The child can access any beans defined in the parent, but the parent has no access to beans defined in the child
  • ContextLoaderListener is a ServletListener. So in the JSP/Servlet spec a Servlet Listener gets called by the container when certain
    events occur. In this case it gets called right after when the
    ServletContext is created for the web application. When it gets
    called, inside the ContextLoaderListener it will create/instantiate
    an ApplicationContext and load in the xml file you set with the
    context-param name and value tags.
  • The contextConfigLocation param is used in conjunction with this Spring listener org.springframework.web.context.ContextLoaderListener
  • ContextLoaderListener executes the bootstrap of the listener to start up Spring's root WebApplicationContext
  • ContextLoaderListener is a class that starts Spring container. Basically every Spring application consists of several beans and wiring (declarative description of which beans depend on each other). This description was historically written in XML (these days we have annotations, Java configuration, CLASSPATH scanning, etc.)
  • ContextLoaderListener reads that file, finds your classes, instantiates them and wires. All your beans are then placed inside a container.

The documentation does explain the difference:
schedule:
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well.
So, suppose the delay is 5 seconds, and each task takes 2 seconds, you would get
TTWWWTTWWWTTWWWTT
where T means 1 second for the task execution, and W means 1 second waiting.
But now suppose that a long GC (represented by a G) happens and delays the second task, the third one will start 5 seconds after the start of the second one, as if the long GC didn't happen:
TTWWWGGTTWWWTTWWWTT
The third task starts 5 seconds after the second one.
scheduleAtFixedRate:
In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up.".
So, with the same delay as above, and the same GC, you would get
TTWWWGGTTWTTWWWTT
The third task task starts 3 seconds instead of 5 after the second one, to catch up.
Using a Trigger you can calculate the next execution time on the fly.
Something like this should do the trick (adapted from the Javadoc for @EnableScheduling):
@Configuration
@EnableScheduling
public class MyAppConfig implements SchedulingConfigurer {

    @Autowired
    Environment env;

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }

    @Bean(destroyMethod = "shutdown")
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(100);
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
        taskRegistrar.addTriggerTask(
                new Runnable() {
                    @Override public void run() {
                        myBean().getSchedule();
                    }
                },
                new Trigger() {
                    @Override public Date nextExecutionTime(TriggerContext triggerContext) {
                        Calendar nextExecutionTime =  new GregorianCalendar();
                        Date lastActualExecutionTime = triggerContext.lastActualExecutionTime();
                        nextExecutionTime.setTime(lastActualExecutionTime != null ? lastActualExecutionTime : new Date());
                        nextExecutionTime.add(Calendar.MILLISECOND, env.getProperty("myRate", Integer.class)); //you can get the value from wherever you want
                        return nextExecutionTime.getTime();
                    }
                }
        );
    }
}
ust add bean to your config:
 @Bean()
 public ThreadPoolTaskScheduler taskScheduler() {
    return new ThreadPoolTaskScheduler();
 }

@Scheduled doesn't support call method of beans, such as #{authorBean.getA()}.

Spring EL:
http://www.mkyong.com/spring3/spring-el-method-invocation-example/
 @Value("#{'mkyong'.toUpperCase()}")
 private String name;

 @Value("#{priceBean.getSpecialPrice()}")
 private double amount;
Navigating properties or invoking method of other beans
<property name="property" value="#{otherBean.property}"/>
<property name="property" value="#{otherBean.method()}"/>
<property name="strLength" value="#{otherBean.method().length()}"/>

Accessing class-scoped methods and properties
Sometimes there is a need to wire some constans or results of a static method, say, I would like to configure my bean with minimum integer value Integer.MIN_VALUE.

SpEL introduced T() operator which gives you access to static methods and constants on a given class.
<property name="prop" value="#{T(java.lang.Integer).MIN_VALUE}"/>
<property name="prop" value="#{T(java.lang.Integer).MAX_VALUE}"/>
<property name="randomValue" value="#{T(java.lang.Math).random()}" />

How to avoid exceptions
<property name="prop" value="#{otherBean.method()?.toUpperCase()}"/>
Note that you will still get BeanCreationException if try to set null value to a property of primitive type.

In the following example strLength will get length of a string returned by method().

<property name="strLength" value="#{otherBean.method()?.length()}" />
If method() returns null you will get BeanCreationException caused by:

java.lang.IllegalArgumentException: Cannot convert value of type [null] to required type [int] for property 'strLength'

Conditional evaluation
<property name="strLength" 
    value="#{otherBean.method() != null ? otherBean.method().length() : -1}" />
Regular Expressions
<property name="onlyDigits" value="#{otherMean.method() matches '\d+'}" />


http://www.petrikainulainen.net/programming/spring-framework/spring-from-the-trenches-using-environment-specific-cron-expressions-with-the-scheduled-annotation/
@Scheduled(cron = "${scheduling.job.cron}")

fixedDelay task:
1
@Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds}")
fixedRate task:
1
@Scheduled(fixedRateString = "${fixedRate.in.milliseconds}")
cron expression based task:
1
@Scheduled(cron = "${cron.expression}")
http://www.baeldung.com/spring-async
When a method return type is a Future, exception handling is easy – Future.get() method will throw the exception.
But, if the return type is voidexceptions will not be propagated to the calling thread. Hence we need to add extra configurations to handle exceptions.
We’ll create a custom async exception handler by implementingAsyncUncaughtExceptionHandler interface. The handleUncaughtException() method is invoked when there are any uncaught asynchronous exceptions:
public class CustomAsyncExceptionHandler  implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
        System.out.println("Exception message - " + throwable.getMessage());
        System.out.println("Method name - " + method.getName());
        for (Object param : obj) {
            System.out.println("Parameter value - " + param);
        }
    }
   
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return new CustomAsyncExceptionHandler();
}
https://dzone.com/articles/spring-async-and-exception
In practice you will likely use the ThreadPoolTaskExecutor or theSimpleAsyncTaskExecutor. When doing so you might at times wonder why a task has not been executed. This happens when an exception occurs inside the method you are trying to execute asynchronous. The aforementioned task executors do not handle the exceptions so the execution fails silently. This problem can be solved by implementing your own AsyncTaskExecutor which handles the exceptions by logging them (or in any other way you wish).


https://spring.io/guides/gs/scheduling-tasks/
@Scheduled(fixedRate = 5000)
@EnableScheduling
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html


http://stackoverflow.com/questions/6267138/spring-autowire-a-list
Spring 4 supports the ability to automatically collect all beans of a given type and inject them into a collection or array.
   @Autowired
   List<Vehicle> vehicles;//contains car and bus

MyContextListenerBase extends ContextLoaderListener {
service = getCurrentWebApplicationContext().getBean(XService.class);
}
http://stackoverflow.com/questions/17656046/autowired-in-servletcontextlistener

http://cloud.spring.io/spring-cloud-static/docs/1.0.x/spring-cloud.html
A Spring @Bean that is marked as @RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.
http://cloud.spring.io/spring-cloud-config/
http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html
Spring Cloud Configuration Server

Refreshable Configuration
The ProjectNameRestController is annotated with @RefreshScope, a Spring Cloud scope that lets any bean recreate itself (and re-read configuration values from the configuration service) in-place. In this case, the ProjectNameRestController will be recreated - its lifecycle callbacks honored and @Value and @Autowired injects re-established - whenever a refresh is triggered.

Fundamentlaly, all refresh-scoped beans will refresh themselves when they receive a Spring ApplicationContext-event of the type RefreshScopeRefreshedEvent. There are various ways to trigger the refresh.

http://sunmingtao.blogspot.com/2012/10/what-does-contextloaderlistener-do-in.html

http://www.importnew.com/19102.html


3、@Lazy可以延迟依赖注入:
Lazy
@Service
public class UserService extends BaseService<User> {
}
@Lazy
@Autowired
private UserService userService;
我们可以把@Lazy放在@Autowired之上,即依赖注入也是延迟的;当我们调用userService时才会注入。即延迟依赖注入到使用时。同样适用于@Bean。
https://solidsoft.wordpress.com/2015/09/29/annotation-driven-event-listeners-in-spring-4-2/
To get a notification about an event (both Spring event and custom domain event) a component implementingApplicationListener with onApplicationEvent has to be created.
1
2
3
4
5
6
7
8
9
10
11
@Component
class OldWayBlogModifiedEventListener implements
                        ApplicationListener<OldWayBlogModifiedEvent> {
    (...)
    @Override
    public void onApplicationEvent(OldWayBlogModifiedEvent event) {
        externalNotificationSender.oldWayBlogModified(event);
    }
}
It works fine, but for every event a new class has to be created which generates boilerplate code.
In addition our event has to extend ApplicationEvent class – the base class for all application events in Spring.
1
2
3
4
5
6
7
8
9
10
class OldWayBlogModifiedEvent extends ApplicationEvent {
    public OldWayBlogModifiedEvent(Blog blog) {
        super(blog);
    }
    public Blog getBlog() {
        return (Blog)getSource();
    }
}
Please notice that using domain objects in the events has notable drawback and is not the best idea in many situations. Pseudodomain objects in the code examples were used to not introduce unnecessary complexity.
@EventListener
public void blogModified(BlogModifiedEvent blogModifiedEvent) {
    externalNotificationSender.blogModified(blogModifiedEvent);
}
Under the hood Spring will create an ApplicationListener instance for the event with a type taken from the method argument. There is no limitation on the number of annotated methods in one class – all related event handlers can be grouped into one class.
@Async    //Remember to enable asynchronous method execution
          //in your application with @EnableAsync
@EventListener(condition = "#blogModifiedEvent.importantChange")
public void blogModifiedSpEL(BlogModifiedEvent blogModifiedEvent) {
    externalNotificationSender.blogModifiedSpEL(blogModifiedEvent);
}
http://www.baeldung.com/rest-template
RestTemplate restTemplate = new RestTemplate();
Quote quote = restTemplate.getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote.class);

2.1. Get Plain JSON
ResponseEntity<String> response =
  restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
Foo foo = restTemplate.getForObject(fooResourceUrl + "/1", Foo.class);
restTemplate.delete(entityUrl);

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
      new HttpComponentsClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(timeout);
    return clientHttpRequestFactory;
}
And we can use HttpClient for further configuration options – as follows:

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    RequestConfig config =
      RequestConfig.custom()
                   .setConnectTimeout(timeout)
                   .setConnectionRequestTimeout(timeout)
                   .setSocketTimeout(timeout)
                   .build();
    CloseableHttpClient client =
      HttpClientBuilder.create().setDefaultRequestConfig(config).build();
    return new HttpComponentsClientHttpRequestFactory(client);
}
http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring/
  • @Component: 标注一个普通的Spring Bean类
  • @Controller: 标注一个控制器组件类
  • @Service: 标注一个业务逻辑组件类
  • @Repository: 标注一个DAO组件类
@Resource位于javax.annotation包下,是来自JavaEE规范的一个Annotation,Spring直接借鉴了该Annotation,通过使用该Annotation为目标Bean指定协作者Bean。使用@Resource<property.../>元素的ref属性有相同的效果。
@Resource不仅可以修饰setter方法,也可以直接修饰实例变量,如果使用@Resource修饰实例变量将会更加简单,此时Spring将会直接使用JavaEE规范的Field注入,此时连setter方法都可以不要。

使用@PostConstruct和@PreDestroy定制生命周期行为

@PostConstruct@PreDestroy同样位于javax.annotation包下,也是来自JavaEE规范的两个Annotation,Spring直接借鉴了它们,用于定制Spring容器中Bean的生命周期行为。它们都用于修饰方法,无须任何属性。其中前者修饰的方法时Bean的初始化方法;而后者修饰的方法时Bean销毁之前的方法。

Spring4.0增强的自动装配和精确装配

Spring提供了@Autowired注解来指定自动装配,@Autowired可以修饰setter方法、普通方法、实例变量和构造器等。当使用@Autowired标注setter方法时,默认采用byType自动装配策略。在这种策略下,符合自动装配类型的候选Bean实例常常有多个,这个时候就可能引起异常,为了实现精确的自动装配,Spring提供了@Qualifier注解,通过使用@Qualifier,允许根据Bean的id来执行自动装配。
AspectJ是一个基于Java语言的AOP框架,提供了强大的AOP功能,其他很多AOP框架都借鉴或采纳其中的一些思想。其主要包括两个部分:一个部分定义了如何表达、定义AOP编程中的语法规范,通过这套语法规范,可以方便地用AOP来解决Java语言中存在的交叉关注点的问题;另一个部分是工具部分,包括编译、调试工具等。
AOP实现可分为两类
  1. 静态AOP实现: AOP框架在编译阶段对程序进行修改,即实现对目标类的增强,生成静态的AOP代理类,以AspectJ为代表
  2. 动态AOP实现: AOP框架在运行阶段动态生成AOP代理,以实现对目标对象的增强,以Spring AOP为代表
一般来说,静态AOP实现具有较好的性能,但需要使用特殊的编译器。动态AOP实现是纯Java实现,因此无须特殊的编译器,但是通常性能略差。
  • 切面(Aspect): 切面用于组织多个Advice,Advice放在切面中定义
  • 连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用,或者异常的抛出。在Spring AOP中,连接点总是方法的调用
  • 增强处理(Advice): AOP框架在特定的切入点执行的增强处理。处理有“around”、“before”和“after”等类型
  • 切入点(Pointcut): 可以插入增强处理的连接点。简而言之,当某个连接点满足指定要求时,该连接点将被添加增强处理,该连接点也就变成了切入点
X. SFTP
http://stackoverflow.com/questions/26412867/spring-integration-pipe-closed-exception-with-sftp-outbound-channel-adapter
I suggest you upgrade to a newer version of Spring Integration; the current version is 4.0.4.
Or you can simply disable session caching.
We rewrote session caching a couple of years ago (in 2.2; current version 2.2.6) and it now checks for a stale session when a cached session is retrieved from the cache.
The cache-sessions attribute is no longer available; you have to wrap the session factory in a CachingSessionFactory to cache sessions now.
Are you using a CachingConnectionFactory? If you are only using one session per 8 hours, you are not benefiting at all from a cache and, it is possible, the library doesn't detect a closed session until the next time it's used.

Starting with version 3.0, sessions are no longer cached by default.
http://docs.spring.io/autorepo/docs/spring-integration/4.3.0.BUILD-SNAPSHOT/reference/html/sftp.html#sftp-session-caching
If you experience connectivity problems and would like to trace Session creation as well as see which Sessions are polled you may enable it by setting the logger to TRACE level (e.g., log4j.category.org.springframework.integration.file=TRACE)

Since we use JSch libraries (http://www.jcraft.com/jsch/) to provide SFTP support, at times you may require more information from the JSch API itself, especially if something is not working properly (e.g., Authentication exceptions). Unfortunately JSch does not use commons-logging but instead relies on custom implementations of their com.jcraft.jsch.Logger interface. As of Spring Integration 2.0.1, we have implemented this interface. So, now all you need to do to enable JSch logging is to configure your logger the way you usually do. For example, here is valid configuration of a logger using Log4J.
log4j.category.com.jcraft.jsch=DEBUG
http://stackoverflow.com/questions/2003419/com-jcraft-jsch-jschexception-unknownhostkey
Configure JSch to not use "StrictHostKeyChecking" (this introduces insecurities and should only be used for testing purposes), using the following code:
java.util.Properties config = new java.util.Properties(); 
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
http://stackoverflow.com/questions/30178936/jsch-sftp-security-with-session-setconfigstricthostkeychecking-no

Disabling the StrictHostKeyChecking option will make the connection less secure than having the option enabled, because it will let you connect to remote servers without verifying their SSH host keys. If the option is enabled, you will only be able to connect to servers which keys are known to your SSH client.
You will have to decide what that means for your specific use case - are the servers you are connecting on a private, local network or do you connect over the internet? Is this a testing or production environment?
When in doubt, it is better to err on the side of more security. I would recommend enabling StricktHostKeyChecking and using the setKnownHosts method to provide a file which contains the remote host keys.
The file needs to be available on the client which runs your program. If you have access to a Linux machine you can generate the file yourself: ssh-keyscan -t rsa hostname > known_hosts Hostname would be the target server you want to connect to in this case. Then just pass the file to the setKnownHosts method.

Yes, it will make the connection (and the transfer) insecure. Particularly, it makes the connection open to Man-in-the-middle attacks.
You should never set StrictHostKeyChecking to no, unless you do not care about security (such as when connecting within private network).
The strict-host-key-checking command specifies how host keys are checked during the connection and authentication phase. By default, strict host key checking is disabled. When disabled the SSH client verifies the incoming host key against the keys in the known hosts list. If the host key does not match an existing known host entry for the remote server, the connection is rejected. If the known host list does not contain a host key for the remote server, the SSH client automatically accepts the host and adds its host key to the known host list.
When strict host key checking is enabled, the SSH client connects only to known hosts with valid SSH host keys that are stored in the known hosts list. Host keys not in the known host list are rejected.
This command is valid when the SSH client profile connects to an SSH server.
http://anahorny.blogspot.com/2013/05/solution-for-comjcraftjschjschexception.html
Just a random investigation with a workaround. So trying to connect to SFTP server using jsch library, but getting a nasty com.jcraft.jsch.JSchException: reject HostKey exception. This host is already present in ~/.ssh/known_hosts file, so it should not be problem, but it is. It turns out this problem happens if SFTP server is running on Ubuntu and strictHostKey is set to true, but it doesn't happen on Fedora. I suppose this is because host entries in the known_hosts file on Ubuntu are encrypted in a different way than in known_hosts on Fedora, so it cannot be recognized or decrypted by JSch library. Now all you need to do is manually add host entries to the file. Basically you just get the public key for the host where SFTP server is running using this command:
1
ssh-keyscan -t rsa sftp_server_ip_address_or_hostname
https://github.com/spring-projects/spring-integration/blob/master/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpServerTests.java
session.write(new ByteArrayInputStream("foo".getBytes()), "bar");
list = session.list(".");
assertEquals("bar", list[0].getFilename());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
session.read("bar", outputStream);
assertEquals("foo", new String(outputStream.toByteArray()));
session.remove("bar");
session.close();

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts