IBM Domino database configuration with Spring boot - spring-boot

I am trying to configure IBM domino database with spring boot to fetch the document from IBM domino server.I have added domino NCSO jar in local maven repo and I have wrote the sample Java program for domino connection. Now I want to convert it into spring boot code to connect with domino db and use the database connection in other services to get the data from views. Appreciated for any hits/instruction for the same.
JAVA Sample :
import lotus.domino.Database;
import lotus.domino.NotesFactory;
import lotus.domino.Session;
public class JavaAgent {
public static void main(String[] args) {
try {
String host = "test.xxx.xxx.com:63148";
Session s = NotesFactory.createSession(host);
String p = s.getCommonUserName();
System.out.println(p);
Database db = s.getDatabase("test.xxx.xxx.com", "s.nsf");
System.out.println(db.getFilePath());
} catch (Exception e) {
e.printStackTrace();
}
}
}

I am able to connect in spring boot by adding below code in spring boot configuration class:
#Bean
public DbDirectory dominoConnection() throws NotesException {
Session session = NotesFactory.createSession(host, username, password);
String p = session.getCommonUserName();
DbDirectory dir = session.getDbDirectory(null);
String server = dir.getName();
return dir;
}
#Bean
public Session dominoDBSession() throws NotesException {
Session session = NotesFactory.createSession(host, username, password);
return session;
}

Related

Setting up Spring Data JPA with AD Service Principal in application.properties

So as per documentation in Azure:
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
public class AADServicePrincipal {
public static void main(String[] args) throws Exception{
String principalId = "1846943b-ad04-4808-aa13-4702d908b5c1"; // Replace with your AAD service principal ID.
String principalSecret = "..."; // Replace with your AAD principal secret.
SQLServerDataSource ds = new SQLServerDataSource();
ds.setServerName("aad-managed-demo.database.windows.net"); // Replace with your server name
ds.setDatabaseName("demo"); // Replace with your database
ds.setAuthentication("ActiveDirectoryServicePrincipal");
ds.setAADSecurePrincipalId(principalId);
ds.setAADSecurePrincipalSecret(principalSecret);
try (Connection connection = ds.getConnection();
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()")) {
if (rs.next()) {
System.out.println("You have successfully logged on as: " + rs.getString(1));
}
}
}
}
We can use this to create a Data Source that can connect via AD Service Principal to SQL Server, and insert it as a bean I believe as:
#Bean
#Primary
DataSource dataSource() throws SQLException {
String principalId = "1846943b-ad04-4808-aa13-4702d908b5c1"; // Replace with your AAD service principal ID.
String principalSecret = "..."; // Replace with your AAD principal secret.
SQLServerDataSource ds = new SQLServerDataSource();
ds.setServerName("aad-managed-demo.database.windows.net"); // Replace with your server name
ds.setDatabaseName("demo"); // Replace with your database
ds.setAuthentication("ActiveDirectoryServicePrincipal");
ds.setAADSecurePrincipalId(principalId);
ds.setAADSecurePrincipalSecret(principalSecret);
return ds;
}
But what I am looking for is -
Can we configure this whole thing via YAML/application.properties so that it gets auto configured with Data JPA ?
If not, can the above process work ?

How to integrate a Spring RMI server with a pure Java RMI client which is a non-spring Swing GUI?

I'm migrating a J2EE EJB application to Spring services. It's a desktop application which has a Swing GUI and to communicate to the J2EE server it uses RMI. I have created a simple spring service with spring boot which exports a service by using spring remoting, RMIServiceExporter. The client is a rich client and have a complicated architecture so i'm trying make minimum changes to it to call the spring rmi service.
So in summary I have a plain RMI client and a spring RMI server. I have learned that spring rmi abstracts pure java rmi so in my case they don't interoperate.
I will show the code below but the current error is this. Note that my current project uses "remote://". So after I have got this error I have also tried "rmi://". But, in both cases it gives this error.
javax.naming.CommunicationException: Failed to connect to any server. Servers tried: [rmi://yyy:1099 (No connection provider for URI scheme "rmi" is installed)]
at org.jboss.naming.remote.client.HaRemoteNamingStore.failOverSequence(HaRemoteNamingStore.java:244)
at org.jboss.naming.remote.client.HaRemoteNamingStore.namingStore(HaRemoteNamingStore.java:149)
at org.jboss.naming.remote.client.HaRemoteNamingStore.namingOperation(HaRemoteNamingStore.java:130)
at org.jboss.naming.remote.client.HaRemoteNamingStore.lookup(HaRemoteNamingStore.java:272)
at org.jboss.naming.remote.client.RemoteContext.lookupInternal(RemoteContext.java:104)
at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:93)
at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:146)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at com.xxx.ui.common.communication.JbossRemotingInvocationFactory.getRemoteObject(JbossRemotingInvocationFactory.java:63)
at com.xxx.gui.comm.CommManager.initializeSpringEJBz(CommManager.java:806)
at com.xxx.gui.comm.CommManager.initializeEJBz(CommManager.java:816)
at com.xxx.gui.comm.CommManager.initializeAndLogin(CommManager.java:373)
at com.xxx.gui.comm.CommManager$2.doInBackground(CommManager.java:273)
at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at javax.swing.SwingWorker.run(SwingWorker.java:334)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
I have searched for how we can interoperate spring rmi and plain/pure java rmi and i read several answers from similar questions at stackoverflow and web but i couldn't find anything useful or fits my case because even the best matched answer says only that it doesn't interoperate.
I thought that maybe i need to turn my swing gui client to spring by using spring boot but i couldn't be sure about application context since i don't want to break existing client code. So i have looked for maybe there is something like partial spring context so that maybe i can put only my CommManager.java client code to it and spring only manages this file.
And then I thought that maybe I need to change my RMI server to force spring to create some kind of plain/pure Java RMI instead of default spring RMI thing. I say thing because I read something about spring rmi that explains it's an abstraction over rmi and we can force it to create standard RMI stub.
While I'm searching for a solution i have encountered the Spring Integration but I couldn't understand it really since it looks like an other abstraction but it also tell something about adapters. Since I have seen "adapter" maybe it is used for this kind of integration/legacy code migration cases. But I couldn't go further.
Client Side:
CommManager.java
private boolean initializeEJBz(String userName, String password) throws Exception {
...
ri = RemoteInvocationFactory.getRemoteInvocation(user, pass);
if (ri != null) {
return initializeEJBz(ri);
} else {
return false;
}
}
RemoteInvocationFactory.java
package com.xxx.ui.common.communication;
import javax.naming.NamingException;
public final class RemoteInvocationFactory {
private static final CommunicationProperties cp = new CommunicationProperties();
public static synchronized RemoteInvocation getRemoteInvocation(
byte[] userName, byte[] password) throws NamingException {
String url = System.getProperty("rmi://xxx.com:1099");
if (url != null) {
return new JbossRemotingInvocationFactory(userName, password, url);
}
return null;
}
...
JbossRemotingInvocationFactory.java
package com.xxx.ui.common.communication;
...
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
...
import java.util.Hashtable;
import java.util.concurrent.TimeUnit;
public class JbossRemotingInvocationFactory implements RemoteInvocation {
private final byte[] userName, password;
private final String providerURL;
private volatile InitialContext initialContext;
private final SecretKey secretKey;
private static final String SSL_ENABLED = "jboss.naming.client.connect.options.org.xnio.Options.SSL_ENABLED";
private static final String SSL_STARTTLS = "jboss.naming.client.connect.options.org.xnio.Options.SSL_STARTTLS";
private static final String TIMEOUT = "jboss.naming.client.connect.timeout";
private long timeoutValue;
private final boolean startSsl;
#SuppressWarnings("unchecked")
public JbossRemotingInvocationFactory(byte[] userName, byte[] password, String providerURL) {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
secretKey = keyGenerator.generateKey();
this.providerURL = providerURL;
startSsl = Boolean.valueOf(System.getProperty(SSL_ENABLED));
String property = System.getProperty("myproject.connect.timeout");
if (property != null) {
try {
timeoutValue = TimeUnit.MILLISECONDS.convert(Long.parseLong(property), TimeUnit.SECONDS);
} catch (Exception e) {
timeoutValue = TimeUnit.MILLISECONDS.convert(10, TimeUnit.SECONDS);
}
}
Hashtable jndiProperties = new Hashtable();
this.userName = encrypt(userName);
addOptions(jndiProperties);
jndiProperties.put(Context.SECURITY_CREDENTIALS, new String(password, UTF_8));
initialContext = new InitialContext(jndiProperties);
this.password = encrypt(password);
} catch (NamingException | NoSuchAlgorithmException ne) {
throw new RuntimeException(ne);
}
}
#Override
#SuppressWarnings("unchecked")
public <T> T getRemoteObject(Class<T> object, String jndiName) throws NamingException {
if (initialContext != null) {
T value = (T) initialContext.lookup(jndiName);
initialContext.removeFromEnvironment(Context.SECURITY_CREDENTIALS);
initialContext.removeFromEnvironment(Context.SECURITY_PRINCIPAL);
return value;
} else {
throw new IllegalStateException();
}
}
#Override
public <T> T getRemoteObject(Class<T> object) throws NamingException {
throw new IllegalAccessError();
}
...
private void addOptions(Hashtable jndiProperties) {
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
jndiProperties.put("jboss.naming.client.ejb.context", "true");
jndiProperties.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
jndiProperties.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
jndiProperties.put(SSL_STARTTLS, "false");
jndiProperties.put(TIMEOUT, Long.toString(timeoutValue));
if (startSsl) {
jndiProperties.put("jboss.naming.client.remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "true");
jndiProperties.put(SSL_ENABLED, "true");
}
jndiProperties.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS", "JBOSS-LOCAL-USER");
jndiProperties.put(Context.PROVIDER_URL, providerURL);
jndiProperties.put(Context.SECURITY_PRINCIPAL, new String(decrypt(userName), UTF_8));
}
#Override
public void reconnect() {
try {
Hashtable jndiProperties = new Hashtable();
addOptions(jndiProperties);
jndiProperties.put(Context.SECURITY_CREDENTIALS, new String(decrypt(password), UTF_8));
initialContext = new InitialContext(jndiProperties);
} catch (NamingException ignore) {
}
}
}
CommManager.java
private boolean initializeEJBz(RemoteInvocation remoteInvocation) throws Exception {
cs = remoteInvocation.getRemoteObject(CustomerService.class, JNDINames.CUSTOMER_SERVICE_REMOTE);
...
// here is the integration point. try to get RMI service exported.
myService = remoteInvocation.getRemoteObject(HelloWorldRMI.class, JNDINames.HELLO_WORLD_REMOTE);
return true;
}
public static final String CUSTOMER_SERVICE_REMOTE = getRemoteBean("CustomerServiceBean", CustomerService.class.getName());
public static final string HELLO_WORLD_REMOTE = getRemoteBean("HelloWorldRMI", HelloWorldRMI.class.getName());
...
private static final String APPLICATION_NAME = "XXX";
private static final String MODULE_NAME = "YYYY";
...
protected static String getRemoteBean(String beanName, String interfaceName) {
return String.format("%s/%s/%s!%s", APPLICATION_NAME, MODULE_NAME, beanName, interfaceName);
}
Server Side:
HelloWorldRMI.java:
package com.example.springrmiserver.service;
public interface HelloWorldRMI {
public String sayHelloRmi(String msg);
}
HelloWorldRMIImpl:
package com.example.springrmiserver.service;
import java.util.Date;
public class HelloWorldRMIimpl implements HelloWorldRMI {
#Override
public String sayHelloRmi(String msg) {
System.out.println("================Server Side ========================");
System.out.println("Inside Rmi IMPL - Incoming msg : " + msg);
return "Hello " + msg + " :: Response time - > " + new Date();
}
}
Config.java:
package com.example.springrmiserver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.remoting.rmi.RmiServiceExporter;
import org.springframework.remoting.support.RemoteExporter;
import com.example.springrmiserver.service.HelloWorldRMI;
import com.example.springrmiserver.service.HelloWorldRMIimpl;
#Configuration
public class Config {
#Bean
RemoteExporter registerRMIExporter() {
RmiServiceExporter exporter = new RmiServiceExporter();
exporter.setServiceName("helloworldrmi");
//exporter.setRegistryPort(1190);
exporter.setServiceInterface(HelloWorldRMI.class);
exporter.setService(new HelloWorldRMIimpl());
return exporter;
}
}
SpringServerApplication.java:
package com.example.springrmiserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.Collections;
#SpringBootApplication
public class SpringRmiServerApplication {
public static void main(String[] args)
{
//SpringApplication.run(SpringRmiServerApplication.class, args);
SpringApplication app = new SpringApplication(SpringRmiServerApplication.class);
app.setDefaultProperties(Collections.singletonMap("server.port", "8084"));
app.run(args);
}
}
So, my problem is how to interoperate pure/plain/standard java rmi client which is in a swing GUI with spring rmi server?
Edit #1:
By the way if you can provide further explanations or links about internal details of spring RMI stub creation and why they don't interoperate i will be happy. Thanks indeed.
And also, if you look at my getRemoteBean method which is from legacy code, how does this lookup string works? I mean where does rmi registry file or something resides at server or is this the default format or can i customize it?
Edit #2:
I have also tried this kind of lookup in the client:
private void initializeSpringEJBz(RemoteInvocation remoteInvocation) throws Exception {
HelloWorldRMI helloWorldService = (HelloWorldRMI) Naming.lookup("rmi://xxx:1099/helloworldrmi");
System.out.println("Output" + helloWorldService.sayHelloRmi("hello "));
//hw = remoteInvocation.getRemoteObject(HelloWorldRMI.class, "helloworldrmi");
}
Edit #3:
While I'm searching i found that someone in a spring forum suggested that to force spring to create plain java rmi stub we have to make some changes on the server side so i have tried this:
import java.rmi.server.RemoteObject;
public interface HelloWorldRMI extends **Remote** {
public String sayHelloRmi(String msg) throws **RemoteException**;
...
}
...
public class HelloWorldRMIimpl extends **RemoteObject** implements HelloWorldRMI {
...
}
Is the code above on the right path to solve the problem?
Beside that the first problem is the connection setup as you can see in the beginning of the question. Why i'm getting this error? What is the difference between "rmi://" and "remote://" ?
While I was trying to figure out, I could be able to find a solution. It's true that Spring RMI and Java RMI do not interoperate but currently i don't have enough knowledge to explain its cause. I couldn't find any complete explanation about internals of this mismatch yet.
The solution is using plain Java RMI in Spring backend by using java.rmi.*(Remote, RemoteException and server.UnicastRemoteObject).
java.rmi.server.UnicastRemoteObject is used for exporting a remote object with Java Remote Method Protocol (JRMP) and obtaining a stub that communicates to the remote object.
Edit:
I think this post is closely related to this interoperability issue: Java Spring RMI Activation
Spring doesn't support RMI activation. Spring includes an RmiServiceExporter for calling remote objects that contains nice improvements over standard RMI, such as not requiring that services extend java.rmi.Remote.
Solution:
This is the interface that server exports:
package com.xxx.ejb.interf;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface HelloWorldRMI extends Remote {
public String sayHelloRmi(String msg) throws RemoteException;
}
and this is the implementation of exported class:
package com.xxx.proxyserver.service;
import com.xxx.ejb.interf.HelloWorldRMI;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Date;
public class HelloWorldRMIimpl extends UnicastRemoteObject implements HelloWorldRMI {
public HelloWorldRMIimpl() throws RemoteException{
super();
}
#Override
public String sayHelloRmi(String msg) {
System.out.println("================Server Side ========================");
System.out.println("Inside Rmi IMPL - Incoming msg : " + msg);
return "Hello " + msg + " :: Response time - > " + new Date();
}
}
and the RMI Registry is:
package com.xxx.proxyserver;
import com.xxx.proxyserver.service.CustomerServiceImpl;
import com.xxx.proxyserver.service.HelloWorldRMIimpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Collections;
#SpringBootApplication
public class ProxyServerApplication {
public static void main(String[] args) throws Exception
{
Registry registry = LocateRegistry.createRegistry(1200); // this line of code automatic creates a new RMI-Registry. Existing one can be also reused.
System.out.println("Registry created !");
registry.rebind("just_an_alias",new HelloWorldRMIimpl());
registry.rebind("path/to/service_as_registry_key/CustomerService", new CustomerServiceImpl());
SpringApplication app = new SpringApplication(ProxyServerApplication.class);
app.setDefaultProperties(Collections.singletonMap("server.port", "8084")); // Service port
app.run(args);
}
}
Client:
...
HelloWorldRMI helloWorldService = (HelloWorldRMI)Naming.lookup("rmi://st-spotfixapp1:1200/just_an_alias");
System.out.println("Output" + helloWorldService.sayHelloRmi("hello from client ... "));
...

Feign with RibbonClient and Consul discovery without Spring Cloud

I was trying to setup Feign to work with RibbonClient, something like MyService api = Feign.builder().client(RibbonClient.create()).target(MyService.class, "https://myAppProd");, where myAppProd is an application which I can see in Consul. Now, if I use Spring annotations for the Feign client (#FeignClient("myAppProd"), #RequestMapping), everything works as Spring Cloud module will take care of everything.
If I want to use Feign.builder() and #RequestLine, I get the error:
com.netflix.client.ClientException: Load balancer does not have available server for client: myAppProd.
My first initial thought was that Feign was built to work with Eureka and only Spring Cloud makes the integration with Consul, but I am unsure about this.
So, is there a way to make Feign work with Consul without Spring Cloud?
Thanks in advance.
In my opinion, it's not feign work with consul, its feign -> ribbon -> consul.
RibbonClient needs to find myAppProd's serverList from its LoadBalancer.
Without ServerList, error: 'does not have available server for client'.
This job has been done by SpringCloudConsul and SpringCloudRibbon project, of course you can write another adaptor, it's just some glue code. IMHO, you can import this spring dependency into your project, but use it in non-spring way . Demo code:
just write a new feign.ribbon.LBClientFactory, that generate LBClient with ConsulServerList(Spring's class).
public class ConsulLBFactory implements LBClientFactory {
private ConsulClient client;
private ConsulDiscoveryProperties properties;
public ConsulLBFactory(ConsulClient client, ConsulDiscoveryProperties consulDiscoveryProperties) {
this.client = client;
this.properties = consulDiscoveryProperties;
}
#Override
public LBClient create(String clientName) {
IClientConfig config =
ClientFactory.getNamedConfig(clientName, DisableAutoRetriesByDefaultClientConfig.class);
ConsulServerList consulServerList = new ConsulServerList(this.client, properties);
consulServerList.initWithNiwsConfig(config);
ZoneAwareLoadBalancer<ConsulServer> lb = new ZoneAwareLoadBalancer<>(config);
lb.setServersList(consulServerList.getInitialListOfServers());
lb.setServerListImpl(consulServerList);
return LBClient.create(lb, config);
}
}
and then use it in feign:
public class Demo {
public static void main(String[] args) {
ConsulLBFactory consulLBFactory = new ConsulLBFactory(
new ConsulClient(),
new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties()))
);
RibbonClient ribbonClient = RibbonClient.builder()
.lbClientFactory(consulLBFactory)
.build();
GitHub github = Feign.builder()
.client(ribbonClient)
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
interface GitHub {
#RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(#Param("owner") String owner, #Param("repo") String repo);
}
public static class Contributor {
String login;
int contributions;
}
}
you can find this demo code here, add api.github.com to your local consul before running this demo.

Connecting to multiple MySQL db instances using jooq in spring boot application

I have a spring boot application which is using gradle as build tool and jooq for dao class generation and db connection. Previously my application was connecting to single mysql instance. Below are the configuration we used for connecting to single db instance:
spring.datasource.username=user
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.name=ds_name
spring.datasource.schema=ds_schema
spring.jooq.sql-dialect=MYSQL
Current project structure is
a) Main application project MainApp having application.properties with above key-value pairs.
b) Separate application project as DBProject which has jooq's generated DAO classes. MainApp include DBProject as a jar.
I am using gradle as build tool for this.
Everything is working fine till here. But now I have to connect to one more instance of MySQL. So, I have created another db project as DBProject2 which also contains dao classes generated by jooq using another mysql schema. I have created DBProject2 exactly as DBProject is created.
Now, my question is if I include both DBProjects in MainApp as jar then both will use same db configuration as in application.properties. How I can make separate db jars to point to their respective db schemas. I googled alot about this but couldn't find helpful solution.
This is what I do to connect to multiple (additional) data sources in my Play app. I am not sure if it is the best approach, but it works great for me. I have changed names below to be generic.
// In my application.conf
// default data source
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost:3306/myDb?useSSL=false"
db.default.username=myuser
db.default.password="mypassword"
// additional data source
db.anothersource.driver=com.mysql.jdbc.Driver
db.anothersource.url="jdbc:mysql://localhost:3306/myothersource?useSSL=false"
db.anothersource.username=myuser
db.anothersource.password="mypassword"
// Then in Java, I create a JooqContextProvider class to expose both connections.
public class JooqContextProvider {
#Inject
Database db;
#Inject
play.Configuration config;
public JooqContextProvider(){}
/**
* Creates a default database connection for data access.
* #return DSLConext.
*/
public DSLContext dsl() {
return DSL.using(new JooqConnectionProvider(db), SQLDialect.MYSQL);
}
/**
* Creates an anothersource database connection for data access.
* #return DSLConext for anothersource.
*/
public DSLContext anotherDsl() {
return DSL.using(
new JooqAnotherSourceConnectionProvider(
config.getString("db.anothersource.url"),
config.getString("db.anothersource.username"),
config.getString("db.anothersource.password")),
SQLDialect.MYSQL);
}
}
// Then I needed to implement my JooqAnotherSourceConnectionProvider
public class JooqAnotherSourceConnectionProvider implements ConnectionProvider {
private Connection connection = null;
String url;
String username;
String password;
public JooqAnotherSourceConnectionProvider(String url, String username, String password){
this.url = url;
this.username = username;
this.password = password;
}
#Override
public Connection acquire() throws DataAccessException {
try {
connection = DriverManager.getConnection(url, username, password);
return connection;
}
catch (java.sql.SQLException ex) {
throw new DataAccessException("Error getting connection from data source", ex);
}
}
#Override
public void release(Connection releasedConnection) throws DataAccessException {
if (connection != releasedConnection) {
throw new IllegalArgumentException("Expected " + connection + " but got " + releasedConnection);
}
try {
connection.close();
connection = null;
}
catch (SQLException e) {
throw new DataAccessException("Error closing connection " + connection, e);
}
}
}
// Then in Java code where I need to access one or the other data sources...
jooq.dsl().select().from().where()...
jooq.anotherDsl().select().from().where()...

Weblogic,EJB, $Proxy99 class cast exception

Following are the modules in my project,
1. EJB module (version 3): We prepare ejb jar of this module and deploy on Weblogic11g server. It deals with database operation. It has #local, #Remote interface and #stateless classes implementing #local,#Remote interfaces.
2. Web Application : This web application takes inputs (user uploads file) from users, validates file and inserts data into database. It uses RMI.
Problem: On production (weblogic 11g server ) sometimes we observe exception saying $Proxy99 cannot be cast to "Remote interface name" (for different different classes) e.g com.xyz.fileProcessSetting.FileProcessSttgFacadeRemote.
But after some time when we again upload file, it gets uploaded successfully without any error.
Now, I do not understand how come these remote objects becomes temporarily unavailable? Never faced this issue on development/UAT environment. Also no idea how to reproduce and fix it.
Please help. Thanks in advance.
#Remote
public interface FileProcessSttgFacadeRemote {
//methods
}
#Local
public interface FileProcessSttgFacadeLocal {
//methods
}
#Stateless
public class FileProcessSttgFacade implements FileProcessSttgFacadeLocal, FileProcessSttgFacadeRemote {
//methods
}
in weblogic-ejb-jar.xml
<weblogic-enterprise-bean>
<ejb-name>FileProcessSttgFacade</ejb-name>
<stateless-session-descriptor>
<business-interface-jndi-name-map>
<business-remote>com.xyz.fileProcessSetting.FileProcessSttgFacadeRemote</business-remote>
<jndi-name>FileProcessSttgFacade</jndi-name>
</business-interface-jndi-name-map>
</stateless-session-descriptor>
</weblogic-enterprise-bean>
In web application also in ejb module whenever we want to call methods we use following lookup method to get remote object:
public class someclass extends EjbLocator {
public void someMethod(){
FileProcessSttgFacadeRemote fpfr = (FileProcessSttgFacadeRemote) getService("FileProcessSttgFacade");
//other code
}
}
Following is the class used for JNDI lookup:
public class EjbLocator {
public Object getService(final String jndiName) throws Exception {
try {
obj = getDefaultContext().lookup(jndiName);
} catch (final Exception exp) {
exp.printStackTrace();
}
return obj;
}
protected Context getDefaultContext() {
try {
final Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL,"weblogic");
env.put(Context.SECURITY_CREDENTIALS, "password");
env.put(Context.PROVIDER_URL, "t3://<ip>:<port>");
defaultContext = new InitialContext(env);
return defaultContext;
} catch (final NamingException nExp) {
nExp.printStackTrace();
}
return null;
}
}

Resources