I need to process a file on the app startup and create some objects out of the given information and then add them as beans to the camel context. Eg: Mysql DataSource object.
public static void load(CamelContext context) throws Exception {
JndiRegistry registry = (JndiRegistry) context.getRegistry();
PropertiesComponent pc = context.getComponent("properties", PropertiesComponent.class);
pc.setLocation("classpath:mysql.properties");
for (String mysql: pc.parseUri("{{mysqlConfigs}}").split(",")) {
String MYSQL_DB_URL = pc.parseUri("{{" + mysql + ".url}}");
String MYSQL_DB_USERNAME = pc.parseUri("{{" + mysql + ".username}}");
String MYSQL_DB_PASSWORD = pc.parseUri("{{" + mysql + ".passwd}}");
String DB_NAME = pc.parseUri("{{" + mysql + ".name}}");
MysqlDataSource mysqlDS = new MysqlDataSource();
mysqlDS.setURL(MYSQL_DB_URL);
mysqlDS.setUser(MYSQL_DB_USERNAME);
mysqlDS.setPassword(MYSQL_DB_PASSWORD);
registry.bind(DB_NAME, (DataSource) mysqlDS);
}
}
The code throws exception,
org.apache.camel.impl.PropertyPlaceholderDelegateRegistry cannot be cast to org.apache.camel.impl.JndiRegistry
Same error if I try to cast it to SimpleRegistry. Is there way this can be achieved this way or if any other methodology shall be adopted given that no more contexts are to be added.
Try:
JndiRegistry registry = context.getRegistry(JndiRegistry.class);
Related
I'm using the DataSourceFactory of dropwizard and H2 to create an in-memory db for testing. Here is what I have
private static final String DBNAME = String.format("JDBITest-%d", System.currentTimeMillis());
protected final DataSourceFactory config = new DataSourceFactory();
{
final String url = String.format("jdbc:h2:mem:%s;", DBNAME) +
"MODE=MySQL;" +
"TRACE_LEVEL_FILE=3;" +
"DB_CLOSE_DELAY=-1;" +
"IGNORECASE=TRUE";
System.out.println("Creating in memory H2 using " + url);
BootstrapLogging.bootstrap();
config.setUrl(url);
config.setUser("sa");
config.setDriverClass("org.h2.Driver");
config.setValidationQuery("SELECT 1");
}
#Before
public void setUp() throws Exception {
Server server = Server.createTcpServer().start(); // (4)
System.out.println("Server started and connection is open.");
System.out.println("URL: jdbc:h2:" + server.getURL() + "/mem:" + DBNAME);
}
When this runs I see
Creating in memory H2 using jdbc:h2:mem:JDBITest-1541641621470;MODE=MySQL;TRACE_LEVEL_FILE=3;DB_CLOSE_DELAY=-1;IGNORECASE=TRUE
Server started and connection is open.
URL: jdbc:h2:tcp://0.0.17.56:9092/mem:JDBITest-1541641621470
Why is the TCP 0.0.17.56? I cannot access this nor can I use the H2.jar to access the shell.
There are several wrong things here.
H2 has different connections modes. In your example you configure DataSourceFactory for in memory connection, but then in #Before method you create new instance of H2 with tcp based connection. More about connection modes here.
So now you have basically 2 instances of H2, in memory and tcp and they are completely unrelated. So you probably need to have only 1 connection type configured for you tests.
If you want to connect to your H2 db outside of JVM (from browser for example) - then you need to have tcp-based connection.
To be able to connect to db from browser you also need to run console application. Which should be inside h2.jar with command like that java -jar h2*.jar. More about this here.
And finally, this peace of code should suitable for you (with in-memory connection):
private static final String DBNAME = String.format("JDBITest-%d", System.currentTimeMillis());
private ManagedDataSource dataSource;
#Before
public void setUp() {
System.out.println("Server started and connection is open.");
final String url = String.format("jdbc:h2:mem:%s;", DBNAME) +
"MODE=MySQL;" +
"TRACE_LEVEL_FILE=3;" +
"DB_CLOSE_DELAY=-1;" +
"IGNORECASE=TRUE";
System.out.println("Creating in memory H2 using " + url);
DataSourceFactory config = new DataSourceFactory();
BootstrapLogging.bootstrap();
config.setUrl(url);
config.setUser("sa");
config.setDriverClass("org.h2.Driver");
config.setValidationQuery("SELECT 1");
dataSource = config.build(null, "test");
}
#Test
public void test() throws SQLException {
Connection connection = dataSource.getConnection();
connection.createStatement().executeUpdate("CREATE TABLE TEST (`id` INT)");
connection.createStatement().executeUpdate("INSERT INTO TEST (`id`) VALUES (1)");
ResultSet resultSet1 = connection.createStatement().executeQuery("SELECT * FROM TEST WHERE `id` = 1");
resultSet1.next();
resultSet1.getInt(1);
System.out.println("Found ID: " + resultSet1.getInt(1));
}
Out:
Server started and connection is open.
Creating in memory H2 using jdbc:h2:mem:JDBITest-1541649996267;MODE=MySQL;TRACE_LEVEL_FILE=3;DB_CLOSE_DELAY=-1;IGNORECASE=TRUE
Found ID: 1
I am developing a web project with HSQLDB persistence. My database instance is on server mode, therefore, I need to run a cmd script/ Java method to access my schema.
Tomcat is the container I use to drop my war on port 8080. Gradle is my build system.
Currently I am using the following main method before I deploy my app to properly access my database on runtime:
public static void main(String[] args) throws IOException, ServerAcl.AclFormatException {
final String URL = "file:~/db/cursago";
String user = "user";
String password = "password";
HsqlProperties p = new HsqlProperties();
p.setProperty("server.database.0",URL+";user="+user+";password="+password);
p.setProperty("server.dbname.0","cursago");
Server server = new Server();
server.setProperties(p);
server.setLogWriter(null);
server.setErrWriter(null);
server.start();
System.out.println("Database is running with path: " + URL);
System.out.println("Username: " + user+", Password: " + password);
}
I would like to know if there's a way of making Tomcat/Gradle/IntelliJ IDEA run this main method before a project deploy, instead of running this script by hand.
from here:
you could run the content of your main in the onApplicationEvent like:
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
final String URL = "file:~/db/cursago";
String user = "user";
String password = "password";
HsqlProperties p = new HsqlProperties();
p.setProperty("server.database.0",URL+";user="+user+";password="+password);
p.setProperty("server.dbname.0","cursago");
Server server = new Server();
server.setProperties(p);
server.setLogWriter(null);
server.setErrWriter(null);
server.start();
System.out.println("Database is running with path: " + URL);
System.out.println("Username: " + user+", Password: " + password);
}
}
This will trigger on every event, that could be application started or redeployed and happens before your application handles requests.
You also can wire in your properties.
There are some difficulties if the server is already running and it can't run in this scope only.
The setup is following - I have a timed task that would send verification emails so users:
#Scheduled(cron = " 0 0-59/1 * * * * ")
public void sendVerificationEmails() {
//...
}
And in those emails I need to include a link leading back to the same webapp. However I can not find any references of how to get app's base url without servlet context.
BONUS
It would also help if I could set up thymeleaf template resolver here to work with those links, but for that I need a WebContext which requires an instance of HttpServletRequest.
Suppose your app is using embedded tomcat server, then url to your app may be found as follows:
#Inject
private EmbeddedWebApplicationContext appContext;
public String getBaseUrl() throws UnknownHostException {
Connector connector = ((TomcatEmbeddedServletContainer) appContext.getEmbeddedServletContainer()).getTomcat().getConnector();
String scheme = connector.getScheme();
String ip = InetAddress.getLocalHost().getHostAddress();
int port = connector.getPort();
String contextPath = appContext.getServletContext().getContextPath();
return scheme + "://" + ip + ":" + port + contextPath;
}
Here is an example for embedded jetty server:
public String getBaseUrl() throws UnknownHostException {
ServerConnector connector = (ServerConnector) ((JettyEmbeddedServletContainer) appContext.getEmbeddedServletContainer()).getServer().getConnectors()[0];
String scheme = connector.getDefaultProtocol().toLowerCase().contains("ssl") ? "https" : "http";
String ip = InetAddress.getLocalHost().getHostAddress();
int port = connector.getLocalPort();
String contextPath = appContext.getServletContext().getContextPath();
return scheme + "://" + ip + ":" + port + contextPath;
}
In my setup I have a #Configuration class setting up the context path (hardcoded) and #Value injecting the port number from application.properties. The context path could also be extracted to a properties file and injected the same way, you would use:
#Value("${server.port}")
private String serverPort;
#Value("${server.contextPath}")
private String contextPath;
You can also implement ServletContextAware in your component in order to get a hook to the ServletContext which would also give you the context path.
I am guessing you would like to ship a complete url (including the full server name) in your emails, but you can't really be sure that the e-mail receivers are accessing your application server directly by hostname, i.e. it could be behind a web server, a proxy etc. You could of course add a server name which you know can be accessed from outside as a property as well.
I'm writing Java application with Apache Camel and use JDBC DataSource(Apache commons DBCP).
I can create many connections but all connections are handled in one Oracle client process, what I may see in sessions table select * from v$session.
The question is how to connect from one Java application to different Oracle processes to improve performance? If you know a way to do it using other Java technologies, not used in my example, it is also very interesting.
public static void main(String... args) throws Exception {
Main main = new Main();
String url = "some url";
String user = "user";
String password = "password";
DataSource dataSource = setupDataSource(url, user, password);
// bind dataSource into the registery
main.bind("oraDataSource", dataSource);
main.enableHangupSupport();
main.addRouteBuilder(new MyRouteBuilder());
main.run(args);
}
private static DataSource setupDataSource(String connectURI, String user, String password) {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
ds.setMaxActive(20);
LOG.info("max active conn: " + ds.getMaxActive());
ds.setUsername(user);
ds.setPassword(password);
ds.setUrl(connectURI);
return ds;
}
public class MyRouteBuilder extends RouteBuilder {
Processor logProcessor = new LogProcessor();
Processor createAnswer = new CreateAnswerProc();
Processor dbPaymentProcessor = new DbPaymentQueryProcessor();
/**
* Let's configure the Camel routing rules using Java code...
*/
public void configure() {
from("rabbitmq://localhost:5672/ps.vin_test_send?exchangeType=topic&autoDelete=false&queue=ps.test_send_queue&concurrentConsumers=20&threadPoolSize=20")
.unmarshal().json(JsonLibrary.Jackson, Payment[].class)
.process(dbPaymentProcessor)
.to("jdbc:oraDataSource")
.process(logProcessor)
.process(createAnswer)
.to("rabbitmq://localhost:5672/ps.vin_test?username=test&password=test&exchangeType=topic&autoDelete=false&routingKey=ps.vin_test_key&queue=vin_test_queue&concurrentConsumers=20");
}
So, the way for oracle is to change db propeties from dedicated to shared. And it will share processes between users. but it is not recomended and not give any performance.
Creation of multiple datasources only reduces performance.
I am trying to call RES server (v 7.1) from EAR deployed on WAS (8.5) instance. I was able to invoke rule server from standalone program and its working without any problems.
However my main problem is to invoke EJB deployed on RES server remotely from another EAR deployed on some other WAS instance. In this case we are not able to look-up the EJB remotely.
As per below thread we should bypass the EJB3 IlrSessionFactory API and should use Java EJB API to look up rule sessions directly.
http://www-01.ibm.com/support/docview.wss?uid=swg21586621
Recommendation from IBM is to use standard java api for ejb lookup or to upgrade to Rule Server 7.5 (latest 8.x).
Code snippet
// Initialization
Map<String, Object> outputParms = null;
IlrStatelessSession session=null;
IlrSessionResponse response=null;
// IlrSessionFactory factory = getFactory();
try {
sessionFactory = JRulesInvoker.getFactory();
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
env.put(Context.PROVIDER_URL,"corbaloc:iiop:localhost:28004");
Context ctx = new InitialContext(env);
Object lookupResult = ctx.lookup("ilog.rules.res.session.impl.ejb3.IlrStatelessSessionRemote");
PortableRemoteObject aPortableRemoteObject = new PortableRemoteObject();
session = (IlrStatelessSession) aPortableRemoteObject.narrow(lookupResult, IlrStatelessSession.class);
IlrPath path = new IlrPath(ruleApp, ruleSet);
IlrSessionRequest request = sessionFactory.createRequest();
request.setRulesetPath(path);
request.setInputParameters(inputParms);
request.getTraceFilter().setInfoTotalRulesFired(true);
request.getTraceFilter().setInfoExecutionEvents(true);
request.setTraceEnabled(true);
// session = sessionFactory.createStatelessSession();
System.out.println("created session " + IlrJNDIConstants.STATELESS_SESSION_EJB3_NAME);
response = session.execute(request);
System.out.println(response.getRulesetExecutionTrace().getTotalRulesFired() + " rule(s) fired.");
System.out.println("Execution output=" + response.getRulesetExecutionOutput());
// Return the result(s)
outputParms = response.getOutputParameters();
if (logger.isEnabledFor(Level.DEBUG)) {
if (response.getRulesetExecutionOutput() != null) {
logger.debug("RuleSet execution output: \n" + response.getRulesetExecutionOutput());
}
}
}catch (IlrSessionCreationException cx) {
if (logger.isEnabledFor(Level.ERROR)) {
logger.error(cx.getMessage(), cx);
}
} catch (IlrSessionException e) {
if (logger.isEnabledFor(Level.ERROR)) {
logger.error(e.getMessage(), e);
}
} catch (NamingException e) {
if (logger.isEnabledFor(Level.ERROR)) {
logger.error(e.getMessage(), e);
}
}
Error
Context: idewas/nodes/ide/servers/server1, name: ilog.rules.res.session.impl.ejb3.IlrStatelessSessionRemote: First component in name ilog.rules.res.session.impl.ejb3.IlrStatelessSessionRemote not found.
javax.naming.NameNotFoundException: Context: idewas/nodes/ide/servers/server1, name: ilog.rules.res.session.impl.ejb3.IlrStatelessSessionRemote: First component in name ilog.rules.res.session.impl.ejb3.IlrStatelessSessionRemote not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]
at com.ibm.ws.naming.jndicos.CNContextImpl.mapNotFoundException(CNContextImpl.java:4563)
at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1821)
at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1776)
at com.ibm.ws.naming.jndicos.CNContextImpl.lookupExt(CNContextImpl.java:1433)
at com.ibm.ws.naming.jndicos.CNContextImpl.lookup(CNContextImpl.java:615)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:165)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:179)
at org.apache.aries.jndi.DelegateContext.lookup(DelegateContext.java:161)
at javax.naming.InitialContext.lookup(InitialContext.java:436)
Check in the SystemOut.log of the RES server what are the binding names for EJBs as it looks like there is no ilog.rules.res.session.impl.ejb3.IlrStatelessSessionRemote there. Also if you have two servers on the same host under the same name e.g. server1 you may have interoberability issues and need to set JVM property com.ibm.websphere.orb.uniqueServerName to true. For more details check the following page Application access problems