In the following Connector/J reference for JDBC/MySQL it suggests we cache the instances of InitialContext and Datasource. Would just making it a private static instance solve the caching? Shouldn't one have to be concerned with thread-safety (if at all)? What is the best 'place' to cache this for a web-app (Restlet + glassfish/Java EE + mysql)??
There is a GenericDAO class that is the root of the data-access classes, so to speak. So would just having static instances actually solve the problem? It would force some of the methods to be static which we don't want. Suggestions??
Thanks!
public void doSomething() throws Exception {
/*
* Create a JNDI Initial context to be able to
* lookup the DataSource
**
In production-level code, this should be cached as
* an instance or static variable, as it can
* be quite expensive to create a JNDI context.
**
Note: This code only works when you are using servlets
* or EJBs in a Java EE application server. If you are
* using connection pooling in standalone Java code, you
* will have to create/configure datasources using whatever
* mechanisms your particular connection pooling library
* provides.
*/
InitialContext ctx = new InitialContext();
/*
* Lookup the DataSource, which will be backed by a pool
* that the application server provides. DataSource instances
* are also a good candidate for caching as an instance
* variable, as JNDI lookups can be expensive as well.
*/
DataSource ds =
(DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");
/*
*Remaining code here...
*/
}
If you're using JAX-RS, then you can use #Context annotation.
E.g.
#Context
private ServletContext context;
#GET
#Path("whatevers")
public List<Whatever> getWhatevers() {
DataSource dataSource = Config.getInstance(context).getDataSource();
// ...
}
However, if the #Resource annotation is also supported on your Restlet environment, you could make use of it as good.
#Resource(mappedName="jdbc/MySQLDB")
private DataSource dataSource
This is in turn technically better to be placed in an EJB which you in turn inject by #EJB in your webservice.
#Stateless
public class WhateverDAO {
#Resource(mappedName="jdbc/MySQLDB")
private DataSource dataSource
public List<Whatever> list() {
// ...
}
}
with
#EJB
private WhateverDAO whateverDAO;
#GET
#Path("whatevers")
public List<Whatever> getWhatevers() {
return whateverDAO.list();
}
Following up on BalusC's link, I can confirm that we could do the same thing when using Restlet. However, as per the code in the example to get the config instance you are passing in the ServletContext as an argument. Restlet is like 'another' framework that uses Servlets as an adapter to configure itself. So it'll be tricky to pass the ServletContext as an argument from somewhere else in the code (Restlet uses it's own Context object which is conceptually similar to ServletContext)
For my case a static method returning the cached datasource seems to be 'clean enough' but there could be other design/organization approaches.
Related
I have a java web application developed on Spring framework which uses mybatis. I see that the datasource is defined in beans.xml. Now I want to add a secondary data source too as a backup. For e.g, if the application is not able to connect to the DB and gets some error, or if the server is down, then it should be able to connect to a different datasource. Is there a configuration in Spring to do this or we will have to manually code this in the application?
I have seen primary and secondary notations in Spring boot but nothing in Spring. I could achieve these in my code where the connection is created/retrieved, by connecting to the secondary datasource if the connection to the primary datasource fails/timed out. But wanted to know if this can be achieved by making changes just in Spring configuration.
Let me clarify things one-by-one-
Spring Boot has a #Primary annotation but there is no #Secondary annotation.
The purpose of the #Primary annotation is not what you have described. Spring does not automatically switch data sources in any way. #Primary merely tells the spring which data source to use in case we don't specify one in any transaction. For more detail on this- https://www.baeldung.com/spring-data-jpa-multiple-databases
Now, how do we actually switch datasources when one goes down-
Most people don't manage this kind of High-availability in code. People usually prefer to 2 master database instances in an active-passive mode which are kept in sync. For auto-failovers, something like keepalived can be used. This is also a high subjective and contentious topic and there are a lot of things to consider here like can we afford replication lag, are there slaves running for each master(because then we have to switch slaves too as old master's slaves would now become out of sync, etc. etc.) If you have databases spread across regions, this becomes even more difficult(read awesome) and requires yet more engineering, planning, and design.
Now since, the question specifically mentions using application code for this. There is one thing you can do. I don't advice to use it in production though. EVER. You can create an ASPECTJ advice around your all primary transactional methods using your own custom annotation. Lets call this annotation #SmartTransactional for our demo.
Sample Code. Did not test it though-
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface SmartTransactional {}
public class SomeServiceImpl implements SomeService {
#SmartTransactional
#Transactional("primaryTransactionManager")
public boolean someMethod(){
//call a common method here for code reusability or create an abstract class
}
}
public class SomeServiceSecondaryTransactionImpl implements SomeService {
#Transactional("secondaryTransactionManager")
public boolean usingTransactionManager2() {
//call a common method here for code reusability or create an abstract class
}
}
#Component
#Aspect
public class SmartTransactionalAspect {
#Autowired
private ApplicationContext context;
#Pointcut("#annotation(...SmartTransactional)")
public void smartTransactionalAnnotationPointcut() {
}
#Around("smartTransactionalAnnotationPointcut()")
public Object methodsAnnotatedWithSmartTransactional(final ProceedingJoinPoint joinPoint) throws Throwable {
Method method = getMethodFromTarget(joinPoint);
Object result = joinPoint.proceed();
boolean failure = Boolean.TRUE;// check if result is failure
if(failure) {
String secondaryTransactionManagebeanName = ""; // get class name from joinPoint and append 'SecondaryTransactionImpl' instead of 'Impl' in the class name
Object bean = context.getBean(secondaryTransactionManagebeanName);
result = bean.getClass().getMethod(method.getName()).invoke(bean);
}
return result;
}
}
How does one port from
<sec:global-method-security secured-annotations="disabled">
<sec:protect-pointcut expression='execution(* x.y.z.end*(..))' access='...' />
to spring java-config
#EnableGlobalMethodSecurity
#Configuration
public class MyConfiguration extends WebSecurityConfigurerAdapter {
?
There is a simmilar question here http://forum.spring.io/forum/spring-projects/security/726615-protect-pointcut-in-java-configuration
There's a workaround for it. The security points information is kept in MethodSecurityMetadataSource implementations (which are then used by MethodInterceptor) so we have to create an additional MethodSecurityMetadataSource. As mentioned in the spring forum post the xml pointcut configuration is kept in MapBasedMethodSecurityMetadataSource and processed by ProtectPointcutPostProcessor. we also need an instance of ProtectPointcutPostProcessor. Unfortunately this class is final and package-private so there are 2 options:
create your own class and copy/paste the whole content of the original one (that's what I did)
change the class modifiers with reflection and create an instance of the original one (haven't done that so no idea if it would work fine)
then create the following beans in your context:
#Bean
public Map<String, List<ConfigAttribute>> protectPointcutMap() {
Map<String, List<ConfigAttribute>> map = new HashMap<>();
// all the necessary rules go here
map.put("execution(* your.package.service.*Service.*(..))", SecurityConfig.createList("ROLE_A", "ROLE_B"));
return map;
}
#Bean
public MethodSecurityMetadataSource mappedMethodSecurityMetadataSource() {
// the key is not to provide the above map here. this class will be populated later by ProtectPointcutPostProcessor
return new MapBasedMethodSecurityMetadataSource();
}
// it's either the original spring bean created with reflection or your own copy of it
#Bean
public ProtectPointcutPostProcessor pointcutProcessor() {
ProtectPointcutPostProcessor pointcutProcessor = new ProtectPointcutPostProcessor((MapBasedMethodSecurityMetadataSource) mappedMethodSecurityMetadataSource());
pointcutProcessor.setPointcutMap(protectPointcutMap());
return pointcutProcessor;
}
we've created the necessary beans, now we have to tell spring to use them. I'm assuming you're extending GlobalMethodSecurityConfiguration. by default it creates DelegatingMethodSecurityMetadataSource which contains a list of other MethodSecurityMetadataSources. Depending on what you want to achieve you have following options:
if you want to keep all the other MethodSecurityMetadataSources (like the ones for parsing the #Secured annotations) you can extend the list in the delegating metadata source by overriding the following method:
#Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
return mappedMethodSecurityMetadataSource();
}
it would inject it on first place in the list though which may cause some problems.
if you want to keep the other sources but want yours to be the last in the list then override the following method:
#Override
public MethodSecurityMetadataSource methodSecurityMetadataSource() {
DelegatingMethodSecurityMetadataSource metadataSource = (DelegatingMethodSecurityMetadataSource) super.methodSecurityMetadataSource();
metadataSource.getMethodSecurityMetadataSources().add(mappedMethodSecurityMetadataSource());
return metadataSource;
}
if you want your source to be the only one (you don't want to use #Secured or any other annotations) then you can override the same method, just with different content
#Override
public MethodSecurityMetadataSource methodSecurityMetadataSource() {
return mappedMethodSecurityMetadataSource();
}
that's it! I hope it will help
I followed #marhewa comments and have been able to use the Spring version of class ProtectPointcutPostProcessor by defining the following bean
/**
* Needed to use reflection because I couldn't find a way to instantiate a
* ProtectPointcutPostProcessor via a BeanFactory or ApplicationContext. This bean will process
* the AspectJ pointcut defined in the map; check all beans created by Spring; store the matches
* in the MapBasedMethodSecurityMetadataSource bean so Spring can use it during its checks
*
* #return
* #throws Exception
*/
#Bean(name = "protectPointcutPostProcessor")
Object protectPointcutPostProcessor() throws Exception {
Class<?> clazz =
Class.forName("org.springframework.security.config.method.ProtectPointcutPostProcessor");
Constructor<?> declaredConstructor =
clazz.getDeclaredConstructor(MapBasedMethodSecurityMetadataSource.class);
declaredConstructor.setAccessible(true);
Object instance = declaredConstructor.newInstance(pointcutMethodMetadataSource());
Method setPointcutMap = instance.getClass().getMethod("setPointcutMap", Map.class);
setPointcutMap.setAccessible(true);
setPointcutMap.invoke(instance, pointcuts());
return instance;
}
This way I don't need to duplicate the code of this Spring class.
Cheers
I have following code
public enum MyInstances {
INSTANCE;
private InstanceClass instance;
private MyInstances(String param){initTitanGraph(param);}
private void initTitanGraph(String param){
instance = SomeFactoryClass.open(param);
}
public InstanceClass getInstance(){
return instance;
}
public void destroyInstance(){
//destroy or close all instances of InstanceClass class
}
}
Now I want to call
MyInstances.INSTANCE.getInstance();
to get the instance.
and
MyInstances.INSTANCE.destroyInstance();
to destroy instance.
I am using spring mvc. How can I implement the same class using spring mvc injection such that on application shutdown destroyInstance should be called and I can also use getinstance() to get instance anywhere.
there is no destroy method unless you define it. This doesn't do anything. The actual INSTANCE is still in memory whatever you do, as a singleton.
You are applying th esingleton pattern, just about, to an Enum.
Enums are hardwired by jvm to be singletons, without any extras from the programmer.
Application start and stop in spring can be achieved with #Postconstruct and #Predestory annotations.
We have 4 applications running on a Tomcat7 server. The existing applications work on Hibernate and Spring.
The backend is connected to a second database and some old schemas are kept here live. Each schema is called xxx_live and xxx_test.
When the Tomcat server starts, a JNDI property is set for the right environment.
Test
Local
Live
The properties are parsed on an extention of the PropertySourcesPlaceholderConfigurer class:
public class GenericPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer {
private String application;
private String environment;
private static final String ENVIRONMENT = "environment";
public GenericPropertySourcesPlaceholderConfigurer(String application) throws IOException {
this.application = application;
this.environment = System.getProperty(ENVIRONMENT);
if (this.environment == null) {
this.environment = System.getenv().get(ENVIRONMENT);
}
initPropertySources();
}
/**
* setup default properties configuration
* Default configuration properties look like :
* app-global.properties
* app-environment.properties
* jndi properties
*/
private void initPropertySources() throws IOException {
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(new ResourcePropertySource(new ClassPathResource(MessageFormat.format("properties/{0}-global.properties", application))));
propertySources.addLast(new ResourcePropertySource(new ClassPathResource(MessageFormat.format("properties/{0}/{1}.properties", environment, application))));
propertySources.addLast(new NotFailingJndiPropertySource("jndi"));
setPropertySources(propertySources);
setIgnoreResourceNotFound(false);
setIgnoreUnresolvablePlaceholders(true);
}
}
Now we're migrating everything to MyBatis. Is there a way to inject or parse these properties into my XML configuration?
Something like:
<select id="findAllUsers" parameterType="list" resultType="user">
SELECT * FROM ${mybatis.default_schema}.USER
</select>
Yes, Definitely you can pass this property.
The function declaration in DAO layer (JAVA Mapper for mybatis in spring) would be like
List<User> findAllUsers(#Param("schemaName") String schemaName)
And when you call this function pass the schema name as argument.
Few Suggestions (Assuming you are new to MyBatis)
You should rather configure your Property using spring's util tag in context.xml
i.e. <util:properties id="mailProps" location="classpath:mail.properties" />
Scan for Mappers & Autowire using spring (again in context.xml)
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.foo.bar" />
</bean>
Where com.foo.bar is package where you Java Interface's representing your XML are located.
This way You will actually be using spring's benefits i.e. DI / IOC
parameterType would be String or java.lang.String not list.
If you need further help / any doubts feel free to ask back.
HTH
Thanks.
How can I refresh Spring configuration file without restarting my servlet container?
I am looking for a solution other than JRebel.
For those stumbling on this more recently -- the current and modern way to solve this problem is to use Spring Boot's Cloud Config.
Just add the #RefreshScope annotation on your refreshable beans and #EnableConfigServer on your main/configuration.
So, for example, this Controller class:
#RefreshScope
#RestController
class MessageRestController {
#Value("${message}")
private String message;
#RequestMapping("/message")
String getMessage() {
return this.message;
}
}
Will return the new value of your message String property for the /message endpoint when refresh is invoked on Spring Boot Actuator (via HTTP endpoint or JMX).
See the official Spring Guide for Centralized Configuration example for more implementation details.
Well, it can be useful to perform such a context reload while testing your app.
You can try the refresh method of one of the AbstractRefreshableApplicationContext class: it won't refresh your previously instanciated beans, but next call on the context will return refreshed beans.
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class ReloadSpringContext {
final static String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE beans PUBLIC \"-//SPRING//DTD BEAN//EN\"\n" +
" \t\"http://www.springframework.org/dtd/spring-beans.dtd\">\n";
final static String contextA =
"<beans><bean id=\"test\" class=\"java.lang.String\">\n" +
"\t\t<constructor-arg value=\"fromContextA\"/>\n" +
"</bean></beans>";
final static String contextB =
"<beans><bean id=\"test\" class=\"java.lang.String\">\n" +
"\t\t<constructor-arg value=\"fromContextB\"/>\n" +
"</bean></beans>";
public static void main(String[] args) throws IOException {
//create a single context file
final File contextFile = File.createTempFile("testSpringContext", ".xml");
//write the first context into it
FileUtils.writeStringToFile(contextFile, header + contextA);
//create a spring context
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
new String[]{contextFile.getPath()}
);
//echo the bean 'test' on stdout
System.out.println(context.getBean("test"));
//write the second context into it
FileUtils.writeStringToFile(contextFile, header + contextB);
//refresh the context
context.refresh();
//echo the bean 'test' on stdout
System.out.println(context.getBean("test"));
}
}
And you get this result
fromContextA
fromContextB
Another way to achieve this (and maybe a more simple one) is to use the Refreshable Bean feature of Spring 2.5+
With dynamic language (groovy, etc) and spring you can even change your bean behavior. Have a look to the spring reference for dynamic language:
24.3.1.2. Refreshable beans
One of the (if not the) most
compelling value adds of the dynamic
language support in Spring is the
'refreshable bean' feature.
A refreshable bean is a
dynamic-language-backed bean that with
a small amount of configuration, a
dynamic-language-backed bean can
monitor changes in its underlying
source file resource, and then reload
itself when the dynamic language
source file is changed (for example
when a developer edits and saves
changes to the file on the
filesystem).
I wouldn't recommend you to do that.
What do you expect to happen to singleton beans which their configuration modified? do you expect all singletons to reload? but some objects may hold references to that singletons.
See this post as well Automatic configuration reinitialization in Spring
You can take a look at this http://www.wuenschenswert.net/wunschdenken/archives/138 where once you change any thing in the properties file and save it the beans will be reloaded with the new values.