This main is calling for a session-bean in the same project to send a message to a message-driven-bean in a separate project.
The other project is fully deployed and running without error.
For this project, the session-bean ejb can be deployed. The problem is when i try to run my client main code, netbeans can deploy the code but gives me (WARNING: Exception creating ejb object : [SSSbean]) upon running it. I simply don't see why the ejb object can't be created. Any ideas?
Session Bean is below:
public class SSSbean implements SSSbeanRemote {
#Resource(name = "jms/Topic")
private static Topic topic;
#Resource(name = "jms/TopicConnectionFactory")
private static ConnectionFactory topicFactory;
public SSSbean () {}
#Override
public void createMessage(String messageData) throws JMSException {
Connection topicConnection = null;
Session session = null;
MessageProducer producer = null;
topicConnection = topicFactory.createConnection();
session = topicConnection.createSession(true,0);
topicConnection.start();
producer = session.createProducer(topic);
TextMessage tm = session.createTextMessage();
tm.setText(messageData);
producer.send(tm);
}
#Override
#Remove
public void remove() {
System.out.println("SSSBean:remove()");
}
}
Main is below:
public class Main {
#EJB
private static SSSbeanRemote ss;
public static void main(String[] args) {
// TODO code application logic here
Main client = new Main();
client.bX();
ss.remove();
}
private void bX() {
System.out.println("Main: Client started... ");
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("Enter Suggestion: ");
String suggestion = sc.nextLine();
try{
ss.createMessage(suggestion);
continue;
} catch (JMSException j) {
System.out.println("Error: "+ j.toString());
}
}
}
}
You are trying to inject an EJB within a code that is not managed by the Container.
When your execute your client code, the main() method just ignores the #EJB annotation. The only one that knows what #EJB means and how to to inject a Bean is the Container. Try to execute the client code inside a Aplication Client Container
If you want to retrieve EJB bean from an application which is not managed by container, you can retrieve it from the InitialContext.
Maybe that will bring you little bit closer: https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI
Related
We have an application using Spring Boot and its JMS facility. At runtime, we have different producers that jump online and tell our application the name of the topic or queue to listen to. Right now, we have:
#JmsListener(destination = "helloworld.q")
public void receive(String message) {
LOGGER.info("received message='{}'", message);
}
which works when we send a message to the helloworld.q topic. The problem is, we won't know what the name of the topic will be until runtime, and JmsListener seems to want a constant expression.
Message producers will hook into our ActiveMQ instance and broadcast a message telling us we need to start listening to their topic, such as "Wasabi", "WhitePaper", "SatelliteMajor", "BigBoosters", etc. There is no way to know at runtime which topics we'll need to start listening to.
I've read the Spring documentation that explains how to listen to topics/queues at runtime (sort of):
#Configuration
#EnableJms
public class ReceiverConfig implements JmsListenerConfigurer {
#Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myJmsEndpoint");
endpoint.setDestination("anotherQueue");
endpoint.setMessageListener(message -> {
// processing
});
registrar.registerEndpoint(endpoint);
}
// other methods...
}
I've shoved that into our Receiver config as a test, and it does get called when we send a message. The problem is, Spring makes all this stuff get called automagically and we don't know where and how to give this method the name of the topic/queue the endpoint needs to listen to. Also, the message listener never seems to get called, but that's a separate problem; I'm sure we can solve it if we at least can send the custom topic or queue for it to listen to.
We're using Spring 2.x.
You can use a property placeholder for the destination name
#SpringBootApplication
public class So56226984Application {
public static void main(String[] args) {
SpringApplication.run(So56226984Application.class, args);
}
#JmsListener(destination = "${foo.bar}")
public void listen(String in) {
System.out.println(in);
}
#Bean
public ApplicationRunner runner(JmsTemplate template) {
return args -> template.convertAndSend("baz", "qux");
}
}
Then set the property, e.g. in application.yml for a Spring Boot app, or a command-line property when launching the JVM
-Dfoo.bar=baz
EDIT
You can make the listener bean a prototype and adjust an environment property.
#SpringBootApplication
public class So56226984Application {
public static void main(String[] args) {
SpringApplication.run(So56226984Application.class, args).close();
}
#Bean
public ApplicationRunner runner(JmsTemplate template, JmsListenerEndpointRegistry registry,
ConfigurableApplicationContext context) {
return args -> {
Scanner scanner = new Scanner(System.in);
String queue = scanner.nextLine();
Properties props = new Properties();
context.getEnvironment().getPropertySources().addLast(new PropertiesPropertySource("queues", props));
while (!"quit".equals(queue)) {
System.out.println("Adding " + queue);
props.put("queue.name", queue);
context.getBean("listener", Listener.class);
template.convertAndSend(queue, "qux sent to " + queue);
System.out.println("There are now " + registry.getListenerContainers().size() + " containers");
queue = scanner.nextLine();
}
scanner.close();
};
}
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Listener listener() {
return new Listener();
}
public static class Listener {
#JmsListener(destination = "${queue.name}")
public void listen(String in) {
System.out.println(in);
}
}
}
I want to make periodical REST request with a Dropwizard Backend. More concretely I want to make an GET request to an external REST API every minute and process the result.
I used the quartz here and now I try to use the jersey client to make a REST request. I use guice as my dependency injection.
My application class has the following methods
#Override
public void initialize(final Bootstrap<DockerwizardConfiguration> bootstrap) {
Job everyJob = new EveryTestJob();
bootstrap.addBundle(new JobsBundle(everyJob));
}
#Override
public void run(final DockerwizardConfiguration configuration,
final Environment environment) {
Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(HelloWorldParameter.class)
.annotatedWith(Names.named("helloWorldParameter"))
.toInstance(configuration.getHelloWorldParameter());
}
});
JerseyClientConfiguration conf = configuration.getJerseyClientConfiguration();
conf.setChunkedEncodingEnabled(false);
final Client client = new JerseyClientBuilder(environment).using(conf).build(getName());
environment.jersey().register(new ExternalServiceResource(client)); // How should that be implented with guice
environment.jersey().register(injector.getInstance(HelloWorldResource.class));
}
And my EveryTestJob class is implemented as follows
#Every("1s")
public class EveryTestJob extends Job {
#Override
public void doJob(JobExecutionContext context) throws JobExecutionException {
// logic run every time and time again
}
}
I am unsure how I this can be organized.
I've been trying to figure this out for a while, and this is what I have found out:
The JobBundle is added before any Resources so the JobExecutionContext will not include the client (https://www.dropwizard.io/0.9.2/docs/manual/internals.html)
Tried using the injector but didn't work either (https://github.com/HubSpot/dropwizard-guice)
Finally I stumbled on Jersey 2.0: Create repeating job which showed how to add the client into the context!
Here's my solution:
In the resource class,
#Path("/myPath")
public class myResource {
#Inject
public myResource() {
try {
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.getContext().put"myResource", this); // Inserts myResource into the context
} catch (SchedulerException e) {
// Handle exception
}
}
// Other stuff for api
}
Then in the job class (I'm using Dropwizard-jobs 2.0.1 where doJobs doesn't take in any arguments so I used execute instead),
#Every("10s")
public class myJob extends Job {
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
myResource res = (myResource) context.getScheduler().getContext().get("myResource");
// Do stuff with your resource
} catch (SchedulerException e) {
// Handle exception
}
}
}
Not sure if you have access to the ExternalServiceResource, but I hope this helps!
I need to create a process that will query a webservice to extract information, and then save the data in my database. However, because this process is very time-intensive, I would like to make it run in the background.
Currently, I have a ProcessHandler which is invoked by a button in the UI. This handler creates a Thread which should run the process in the background. However, I am getting HibernateException with the message No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here.
I have defined ProcessHandler in one of the config xml files (there are several) as follows (this is a very generic definition):
<bean class="com.project.ProcessHandler" parent="parentHandler" />
Inside ProcessHandler, the code to invoke this process is also very generic:
Thread t = new Thread(new WorkerThread(alphaManager, bravoManager, charlieManager));
t.start();
This is the current implementation of WorkerThread:
public class WorkerThread implements Runnable {
private Manager alphaManager;
private Manager bravoManager;
private Manager charlieManager;
public WorkerThread() {
this.alphaManager = null;
this.bravoManager = null;
this.charlieManager= null;
}
public WorkerThread(Manager alphaManager, Manager bravoManager, Manager charlieManager) {
this.alphaManager = alphaManager;
this.bravoManager = bravoManager;
this.charlieManager= charlieManager;
}
#Override
public void run() {
// code to query webservice and extract data...
saveToDbMethod(data);
}
#Transactional(propagation = Propagation.REQUIRED)
private void saveToDbMethod(String data) {
// code to process data...
alphaManager.save(entityA);
bravoManager.save(entityB);
charlieManager.save(entityC);
}
}
The default constructor is a leftover from when I tried to define WorkerThread as a bean in (one of) my config xml files.
Can anyone help me by giving me some tips on how to troubleshoot this?
The problem is that you create the Thread manually and expecting it behave like a spring managed bean.
As the ProcessHandler is a legitimate bean, what i would do is following:
1) Create a seaparate service class which would have the managers as dependencies and that #Transactional method:
#Service
public class Service{
private Manager alphaManager;
private Manager bravoManager;
private Manager charlieManager;
public Service(Manager alphaManager, Manager bravoManager, Manager charlieManager) {
this.alphaManager = alphaManager;
this.bravoManager = bravoManager;
this.charlieManager= charlieManager;
}
#Transactional(propagation = Propagation.REQUIRED)
private void saveToDbMethod(String data) {
// code to process data...
alphaManager.save(entityA);
bravoManager.save(entityB);
charlieManager.save(entityC);
}
}
2) Inject the Service into the ProcessHandler:
<bean class="com.project.ProcessHandler" parent="parentHandler">
<property name="service" ref="service">
</bean>
3) Finally pass the Service to the WorkerThread:
public class WorkerThread implements Runnable {
private Service service;
public WorkerThread(Service service) {
this.service = service;
}
#Override
public void run() {
// code to query webservice and extract data...
service.saveToDbMethod(data);
}
}
and:
Thread t = new Thread(new WorkerThread(service));
t.start();
Now your operations should be transactional and within a session.
I am trying to create a minimalist test class for testing some of my CouchBase Lite Mobile classes. I have tried mocking the Application context but have been unsuccessful.
The problem is that the CouchBase manager is accessing some of the unimplemented methods on the MockContext class.
Here are my approaches so far below:
public class ClassToTest extends TestCase {
#Test
public void testGetAllDocumentsBundle() throws Exception {
try {
Manager manager = new Manager(
new AndroidContext(new MockContext()),
Manager.DEFAULT_OPTIONS);
}
catch (Exception e) {
Log.e(TAG, "Exception: " + e);
assertTrue(false);
}
}
And:
#RunWith(AndroidJUnit4.class)
public class ItemReaderTest {
private android.content.Context instrumentationCtx;
#Before
public void setUp() throws Exception {
instrumentationCtx = InstrumentationRegistry.getContext();
}
...
#Test
public void testGetAllDocumentsBundle() throws Exception {
Database database = null;
String databaseName = "test";
try {
Context context = new AndroidContext(instrumentationCtx);
Assert.assertTrue(context != null);
Manager manager = new Manager(context, Manager.DEFAULT_OPTIONS); <--- throws exception because context.getFilesDir(); return null in Couchbase Manager.java constructor
...
}
}
Has anyone been able to do this? Do I absolutely have to use an actual Activity (i.e. create an actual mobile Application and use it's context to be able to test Couchbase mobile at all?
I was able to successfully create the manager and database by doing this:
class MyMockContext extends MockContext {
#Override
public File getFilesDir(){
File f = new
File("/data/user/0/com.example.mypackagename/files");
return f;
}
}
And initializing the manager with this context:
Context context = new AndroidContext(new MyMockContext());
Manager manager = new Manager(context, Manager.DEFAULT_OPTIONS);
However this does make the test dependent on a specific environment and hard-coded path. Perhaps there is a better solve out there...
I have a class that implements ManagedServiceFactory like this:
public class GreeterFactory implements ManagedServiceFactory {
private volatile BundleContext bundleContext =
FrameworkUtil.getBundle(GreeterFactory.class).getBundleContext();
private final Map<String, ServiceRegistration> registrations = new ConcurrentHashMap<>();
#Override
public String getName() {
return "Greeter Factory Implementation";
}
/**
* Greeter Service Factory
* #param pid this is the PID of the Configuration received.
* #param dictionary the Configuration to prepare the service.
* #throws ConfigurationException
*/
#Override
public void updated(String pid, Dictionary<String, ?> dictionary) throws ConfigurationException {
String message = (String) dictionary.get("message");
if (message == null) {
throw new ConfigurationException("message",
"Required property 'message' missing");
}
GreeterService greeter;
synchronized (registrations) {
if (registrations.containsKey(pid)) {
greeter = (GreeterService) bundleContext.getService(registrations.get(pid).getReference());
} else {
// For each new configuration, the factory register a new service with
// the given properties/configuration
greeter = new GreeterImpl();
ServiceRegistration greeterRegistration =
bundleContext.registerService(GreeterService.class.getName(),
greeter,
dictionary);
System.out.print("\nRegistering Config-PID: " + pid + "\n");
registrations.put(pid, greeterRegistration);
}
}
greeter.setMessage(message);
}
#Override
public void deleted(String pid) {
ServiceRegistration component = null;
synchronized (registrations) {
component = registrations.remove(pid);
}
// Calling services from a synchronized block can lead to deadlocks,
// so Dependency Manager must be called outside.
if(component != null) {
bundleContext.ungetService(component.getReference());
}
}
}
The factory works OK. I also have a test case to consume the services created for each configuration sent by the ConfigurationAdmin service, here is the test case:
Configuration configuration1 = configurationAdmin.createFactoryConfiguration("example.factoryservice.greeter", null);
Dictionary properties = new Properties();
properties.put("message", "Hello factory world 1!");
configuration1.update(properties);
TimeUnit.SECONDS.sleep(1);
Configuration configuration2 = configurationAdmin.createFactoryConfiguration("example.factoryservice.greeter", null);
properties = new Properties();
properties.put("message", "Hello factory world 2!");
configuration2.update(properties);
TimeUnit.SECONDS.sleep(1);
ServiceReference<GreeterService> sRef = context.getServiceReference(GreeterService.class);
GreeterService greeterService = context.getService(sRef);
assertEquals("Hello factory world 1!", greeterService.sayHello());
greeterService = context.getService(sRef);
assertEquals("Hello factory world 2!", greeterService.sayHello()); // FAILS!!
Now, I am kind of lost here and I cannot find any documentation about this part, but how do I determine in code what Greeter service to use depending on the configuration I need?
I created in code 2 Greeter configurations, the factory then registered a couple of Greeter services, each with a different configuration, how I decide in code an instance of a Greeter service with Configuration 1?
ManagedServiceFactory is pretty low level. Unless you want to implement a technology, you do not need it. In case you want to implement business logic, use one of the Component Models.
But, to answer your specific question:
You register the GreeterService with the service properties that you get from the configuration. That means that you can filter on these services.
Note, that BundleContext has a function where you can pass OSGi service filter as well. E.g.:
Collection<ServiceReference<GreeterService>> sRefs =
context.getServiceReferences(GreeterService.class,
"(message=Hello factory world 2!)");