MBean non showing if registered on Weblogic Cluster - weblogic

the scenario is:
Application Server: Weblogic 12.2.1.2
Application: an Entenprise Application
The working scenario:
Application deployed on the Admin Server.
JConsole correctly shows my MXBean.
The NOT working scenario:
Application deployed on a cluster of 2 Managed Server.
JMX configured on each Maanaged Server.
JConsole does NOT show my MXBean.
Below my source code relevant fragments.
public class JpaCacheDescriptor {
private String name;
private int size;
#ConstructorProperties({ "name", "size" })
public JpaCacheDescriptor(String name, int size) {
this.name = name;
this.size = size;
}
// Not relevant
}
public interface JpaCacheManager {
List<JpaCacheDescriptor> getCaches();
void clearAll();
}
#Slf4j
public class JpaCacheManagerImpl
extends StandardMBean
implements JpaCacheManager
{
private static ObjectName objectName;
private static MBeanServer getMBeanServer()
throws NamingException
{
InitialContext initialContext = new InitialContext();
return (MBeanServer)initialContext.lookup("java:comp/jmx/runtime");
}
public JpaCacheManagerImpl()
throws NotCompliantMBeanException
{
super(JpaCacheManager.class);
}
public static void register() {
log.info("{ }");
try {
objectName = new ObjectName(String.format(
"${wls.jmx.root}:name=${application.name},version=${application.version},node=%s,type=%s",
System.getProperty("weblogic.Name"),
JpaCacheManager.class.getSimpleName()
));
JpaCacheManagerImpl jpaCacheMBean = new JpaCacheManagerImpl();
StandardMBean standardMBean = new StandardMBean(jpaCacheMBean, JpaCacheManager.class, true); // Force MXBean which is not inferred by #MXBean and MXBean prefix!!!
getMBeanServer().registerMBean(standardMBean, objectName);
log.info("Registered as \"{}\".", objectName.getCanonicalName());
} catch (
InstanceAlreadyExistsException
| MalformedObjectNameException
| MBeanRegistrationException
| NamingException
| NotCompliantMBeanException exception
) {
objectName = null;
log.error(exception.getMessage(), exception);
}
}
public static void unregister() {
log.info("{ }");
if (null == objectName) {
log.warn("MBean not registered!");
} else {
try {
getMBeanServer().unregisterMBean(objectName);
log.info("MBean unregistered.");
}
catch (
InstanceNotFoundException
| MBeanRegistrationException
| NamingException exception
) {
log.error(exception.getMessage(), exception);
}
}
}
#Override
public List<JpaCacheDescriptor> getCaches() {
// Not relevant
}
#Override
public void clearAll() {
// Not relevant
}
}
I spent a lot of time searching for a solution, but with no luck!
Thank you in advance.

I got a solution directly from Oracle ( https://blogs.oracle.com/weblogicserver/managing-weblogic-servers-with-jconsole
).
Please look at following notes:
jconsole -J-Djava.class.path=$JAVA_HOME/lib/jconsole.jar:$JAVA_HOME/lib/tools.jar:$WL_HOME/server/lib/wljmxclient.jar \
-J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote \
-debug
Remote URL:
- Managed Server Runtime : service:jmx:iiop://<MANAGED_HOST>:<PORT>/jndi/weblogic.management.mbeanservers.runtime
- Domain Runtime : service:jmx:iiop://<ADMIN_HOST>:<PORT>/jndi/weblogic.management.mbeanservers.domainruntime
User: <USER_NAME>
Password: <PASSWORD>

Related

RabbitMQ channel lifetime and access in ASP Net Core

I have a ASP NET Core application that will serve as a RabbitMQ producer.I have read the tutorial and guides regarding the RabbitMQ .NET client and i still do not know how to deal with the channel lifetime and concurrent access.
From what i have read i understood the following:
IConnection is threadsafe ,but is costly to create
IModel is not threadsafe but is lightweight
For the IConnection i would initialize it in the Startup and inject it as a singleton (service).
However i I do not know how to deal with IModel management.Lets say i have a couple of services that use it, is it scalable to just :
Solution 1
public void Publish(IConnection connection)
{
using(IModel model=connection.CreateChannel())
{
model.BasicPublish(...);
}
}
Solution 2
From what i have read , i understood that its not really scalable.
So another solution would be to create a separate service which would contain a loop , a ConcurrentQueue, and all services would dispatch messages here.
This service would be the sole publisher to RabbitMQ
Publisher
public class Publisher
{
private CancellationTokenSource tcs=new CancellationTokenSource();
public BlockingCollection<byte[]> messages=new BlockingCollection<byte[]>();
private IModel channel;
private readonly string ExchangeName;
private Task loopTask;
public void Run()
{
this.loopTask=Task.Run(()=>Loop(tcs.Token),tcs.Token);
}
private void Loop(Cancellation token)
{
while(true)
{
token.ThrowIfCancellationRequested();
queue.Take(out byte[]data);
channel.BasicPublish(...,body:data);
}
}
public void Publish(byte[] message)
{
this.queue.Add(message);
}
}
Usage
public class SomeDIService
{
private IConnection connection;
SomeDIService(Publisher publisher)
{
this.publisher=publisher;
}
public void DoSomething(byte[] data)
{
//do something...
this.publisher.Publish(data);
}
}
I would prefer solution 1 but i do not know the performance penalty ,while i do not like solution 2 since i wanted to just publish messages directly to RabbitMQ.Now i have to deal with this long running Task too.
Is there any other solution , am i missing something ? Is there a simpler way?
Update
I mentioned concurrent access.I meant i need a way to publish messages from multiple endpoints (services) to RabbitMQ.
Real scenario
public class Controller1:Controller
{
private SomeDIService service; //uses Publisher
[HttpGet]
public void Endpoint1()
{
this.service.DoSomething();
}
[HttpPost]
public void Endpoint2()
{
this.service.DoSomething();
}
}
public class Controller2:Controller
{
private SomeDIService service;
[HttpGet]
public void Endpoint3()
{
this.service.DoSomething();
}
[HttpPost]
public void Endpoint4()
{
this.service.DoSomething();
}
}
after searching for long time i found this solution and it works very good for me
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace BSG.MessageBroker.RabbitMQ
{
public class Rabbit : IRabbit
{
private readonly EnvConfigModel EnvConfig;
private readonly string _hostname;
private readonly string _password;
private readonly string _exchangeName;
private readonly string _username;
private IConnection _connection;
private IModel _Model;
public Rabbit(IOptions<EnvConfigModel> appSettings)
{
EnvConfig = appSettings.Value;
_Logger = services;
_exchangeName = EnvConfig.Rabbit_ExchangeName;
_hostname = EnvConfig.Rabbit_Host;
_username = EnvConfig.Rabbit_Username;
_password = EnvConfig.Rabbit_Password;
CreateConnection();
_Model = _connection.CreateModel();
}
private void CreateConnection()
{
try
{
var factory = new ConnectionFactory
{
HostName = _hostname,
UserName = _username,
Password = _password,
AutomaticRecoveryEnabled = true,
TopologyRecoveryEnabled = true,
NetworkRecoveryInterval = TimeSpan.FromSeconds(3)
};
_connection = factory.CreateConnection();
}
catch (Exception ex)
{
Console.WriteLine($"Could not create connection: {ex.Message}");
}
}
private bool ConnectionExists()
{
if (_connection != null)
{
return true;
}
CreateShredderConnection();
return _connection != null;
}
public bool PushToQueue(string Message)
{
try
{
if (ConnectionExists())
{
byte[] body = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(Message));
_Model.BasicPublish(exchange: _exchangeName,
routingKey: 1001,
basicProperties: null,
body: body);
}
return true;
}
catch (Exception ex)
{
return false;
}
}
}
}

How to configure distributed Topic or Queue using Apache MQ with JNDI properties and also embeded MQ in applicaiton server

We are moving from weblogic jms to activemq. We put all the activemq required jar files into our application classpath and created one properties file which contains activemq url and connectionfactory details like below:
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:61616
connectionFactoryNames=TestTopicConnectionFactory
topic.mq/TestTopic=TestTopic
During server startup we are loading this properties file as below and starting the MQ broker srevice.
public TestServlet extends HttpServlet {
private MQStartup mqStartup = null;
#Override
public void init(ServletConfig config)
throws ServletException {
super.init(config);
mqStartup = new MQStartup();
mqStartup.startBrokerService();
}
}
public class MQStartup {
private final String bindAddress;
private BrokerService broker = new BrokerService();
public MQStartup(){
MQContext context = new MQContext();
context.loadJndiProperties();
bindAddress = ActiveMQContext.getProperty("java.naming.provider.url");
}
public void startBrokerService() {
broker.addConnector(bindAddress);
broker.start();
}
public void stopBrokerService() {
try {
broker.stop();
}catch (Exception e) {
logger.error("Unable to stop the MQ Broker service " +e);
}
}
}
public class MQContext {
private static final Object singletonLock = new Object();
static Context context = null;
static Properties properties = null;
private boolean loaded = false;
public void loadJndiProperties() {
try {
if (!loaded) {
synchronized (singletonLock) {
URL url = getClass().getClassLoader().getResource("jda-activemq-jndi.properties");
properties = new Properties();
properties.load(url.openStream());
context = new InitialContext(properties);
loaded = true;
}
}
} catch (IOException | NamingException ie) {
logger.error("Failed to load apachemq jndi", ie);
}
}
public static Context getContext() {
return context;
}
public static Properties getProperties() {
return properties;
}
public static String getProperty(String propertyName) {
return properties.getProperty(propertyName);
}
}
In implementation class for producing message we are getting the mq connectionfactory lile below:
TopicConnectionFactory factory = (TopicConnectionFactory) MQContext.getContext().lookup("<topicFactoryName>");
this.topicConnection = factory.createTopicConnection();
this.topicConnection.start();
and then creating topic session and using publisher.publish("message");
But the problem here is we have 3 application instance in cluster and for these 3 instance we have 3 embeded activemq broker service.
When I am producing one message and sending in instance1(suppose webserver is hitting instance1) this message is not consumed by other2 instance.
I googled there is some networkconnector configuration can be helped. But the problem is we are using JNDI and MQ is not a separate installation.
Is there any way to do this with embeded MQ and with JNDI.
Note: In weblogic we have UniformDistributedTopic type of topic which helps to achive the above but in MQ it seems we don't have this kind of topic type.

Singleton Service in weblogic cluster is registering but not invoking activate method

I am implementing a singleton service in a weblogic 12.2.1.2 with EBJ 3.1 in a maven multimodule EAR project.
My singleton service is registering in the cluster.
This is the log from the node where is registered:
<BEA-000189> <The Singleton Service Appscoped_Singleton_Service is now active on this server.>
And this is from other node:
<BEA-003130> <Appscoped_Singleton_Service successfully activated on server iss3.>
The singleton service is implementing the interface weblogic.cluster.singleton.SingletonService but the methods activate and deactivate is not invoked when the nodes starts or shutdown.
I was reading something about versioned EARs and MANIFEST files but not understood this.
I need some help to make methods activate and deactivate be invoked.
This is my class:
import java.io.Serializable;
import javax.inject.Inject;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.test.MyTimerLocal;
import weblogic.cluster.singleton.SingletonService;
public class MySingletonServiceClass implements SingletonService, Serializable, MySingletonServiceInterface {
private static final long serialVersionUID = 3966807367110330202L;
private static final String jndiName = "MySingletonServiceClass";
private int myValue;
#Inject
private MyTimerLocal myTimer;
#Override
public int getMyValue() {
return this.myValue;
}
#Override
public synchronized void setMyValue(final int myValue) {
this.myValue = myValue;
}
#Override
public void activate() {
System.out.println("activate triggered");
Context ic = null;
try {
ic = new InitialContext();
ic.bind(MySingletonServiceClass.jndiName, this);
System.out.println("Object now bound in JNDI at " + MySingletonServiceClass.jndiName);
this.myValue = 5;
final String msg = "###################### MySingletonServiceClass.activate():: Fechamento agendado para " + this.myTimer.agendaExecucao() + " ###############";
System.out.println(msg);
} catch (final NamingException e) {
this.myValue = -1;
e.printStackTrace();
} finally {
try {
if (ic != null) {
ic.close();
}
} catch (final NamingException e) {
e.printStackTrace();
}
}
}
#Override
public void deactivate() {
System.out.println("deactivate triggered");
Context ic = null;
try {
ic = new InitialContext();
ic.unbind(MySingletonServiceClass.jndiName);
System.out.println("Context unbound successfully");
} catch (final NamingException e) {
e.printStackTrace();
}
}
}
Thanks for your time.
I got this working now with this in my src\main\application\META-INF\weblogic-application.xml
<wls:singleton-service>
<wls:class-name>com.test.MySingletonServiceClass</wls:class-name>
<wls:name>Appscoped_Singleton_Service</wls:name>
</wls:singleton-service>

NServiceBus lost messages

I have some messages that are disappearing only in Production.
In the logs it shows the method HandleBeginMessage() being called immediately followed by HandleEndMessage() without any handlers being called in the middle (this only happens sometimes!!!!)
public class OracleMessageModule : IMessageModule
{
public OracleMessageModule()
{
Factory = new OracleSagaSessionFactory();
}
public OracleSagaSessionFactory Factory { get; set; }
public void HandleBeginMessage()
{
Factory.Begin();
}
public void HandleEndMessage()
{
Factory.Complete();
}
public void HandleError()
{
Factory.Complete();
}
}
So I upgraded NServiceBus from 3.2.8 to 4.6.1 (latest version at the moment) and refactored the code:
public class OracleMessageModule : UnitOfWork.IManageUnitsOfWork
{
public OracleMessageModule()
{
Factory = new OracleSagaSessionFactory();
}
public OracleSagaSessionFactory Factory { get; set; }
public void Begin()
{
Factory.Begin();
}
public void End(System.Exception ex = null)
{
Factory.Complete();
}
}
There's the code for OracleSagaSessionFactory:
public class OracleSagaSessionFactory
{
public string ConnectionString { get; set; }
[ThreadStatic]
private static OracleSagaSession current;
public OracleSagaSession Begin()
{
if (current != null)
throw new InvalidOperationException("Current session already exists.");
var session = new OracleSagaSession(ConnectionString);
current = session;
return current;
}
public static OracleSagaSession Current
{
get
{
return current;
}
}
public void Complete()
{
var c = current;
current = null;
if (c != null)
c.Dispose();
}
}
Looking at NServiceBus code looks like in the new version it cleans the Pipeline, so that's why I believe this is the solution, and I don't believe this is my code problem...
Anyone agrees or disagrees?
Edit1: It only happens on my master node with multiple threads and just sometimes. It doesn't happen on my slave nodes that use just one thread.

REST Web Service using Java and Jersey API: Unable to Read data from DB

I am creating a REST Web Service using Java and Jersey API. The basic REST service works fine,but when I add in a DB connection it gives me a Class Not Found Exception and a SQL Exception - No driver found. I have included the ojdbc6.jar file in the Eclipse build path. Using the same code if I create a Java application it runs fine.
I have added my code below. Can some one plz suggest something.
EDIT: I included the jar file in the WEB-INF lib directory. But when I try to execute the code I get the following error: HTTP Status 405 - Method Not Allowed
public class Note {
private int noteId;
private String content;
private Date createdDate;
public Note() {}
public Note(int noteId, String content, Date createdDate) {
this.noteId = noteId;
this.content = content;
this.createdDate = createdDate;
}
public int getNoteId() {
return noteId;
}
public void setNoteId(int noteId) {
this.noteId = noteId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
#Override
public String toString() {
return "Note [content=" + content + ", createdDate=" + createdDate
+ ", noteId=" + noteId + "]";
}
}
public class NoteDAO {
DatabaseAccess data;
Connection connection;
public NoteDAO()
{
try {
data = new DatabaseAccess();
connect();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void connect() throws SQLException
{
try
{
data.connect();
connection = data.connection;
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public Note getNoteById(int id)
{
PreparedStatement prepStmt = null;
try {
String cSQL = "SELECT * FROM NOTE WHERE NOTEID = 12 ";
prepStmt = connection.prepareStatement(cSQL);
prepStmt.setInt(1, id);
ResultSet result = prepStmt.executeQuery();
Note note = new Note();
while (result.next())
{
note.setNoteId(result.getInt(1));
note.setContent(result.getString(2));
note.setCreatedDate( (Date) new java.util.Date(result.getDate(3).getTime()));
}
return note;
} catch (SQLException e) {
e.printStackTrace();
prepStmt = null;
return null;
}
}
}
#Path("/notes")
public class Notes {
#Context
UriInfo uriInfo;
#Context
Request request;
NoteDAO dao = new NoteDAO();
#Path("{note}")
#GET
#Produces(MediaType.APPLICATION_XML)
public Note getNote(
#PathParam("note") String idStr) {
int id = Integer.parseInt(idStr);
Note note = dao.getNoteById(id);
if(note==null)
throw new RuntimeException("Get: Note with " + id + " not found");
return note;
}
public class DatabaseAccess {
Connection connection = null;
public void connect() throws SQLException
{
String DRIVER = "oracle.jdbc.driver.OracleDriver";
String URL = "jdbc:oracle:thin:#xx.xxx.xx.xxx:1521:XXXX";
String UserName = "username";
String Password = "password";
try
{
Class.forName(DRIVER);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
try
{
connection = DriverManager.getConnection(URL,UserName,Password);
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public void disconnect() throws SQLException
{
connection.close();
}
}
If you are using datasources that are managed by the application server, you need to put the ojdbc6.jar library inside the lib folder of your application server.
On JBoss for example, it would be $JBOSS_HOME/server/default/lib.
This is required, because in such case, the datasource is being build when the server starts and independently from your application, which means the server cannot use your application JARs.
If, however, you are pooling the connections yourself, you need to make sure, that the ojdbc6.jar is inside the lib folder of your application WAR archive.