Why does WebSphere create duplicate EJB environment entries? - ejb

I specified a String resource in an EJB with the #Resource annotation. The EJB is packaged within an EJB module. The ejb.jar has an ejb-jar.xml which specifies a default value for the String resource. The ejb.jar is packaged in an ear archive together with a web module.
When the ear is deployed to WebSphere, the Environment entries for EJB modules section shows three EJB entries:
The String resource I mapped for the ejb module;
The String resource I mapped for the ejb module, only this time it is called EJB_fully_qualified_name/resource_name;
The same fully qualified name of the resource but now mapped for the web module.
Unless I provide a default value for all the variants above the resource is not injected. If I add an ejb-jar.xml to the web module, WebSphere displays four entries (one simple name and one fully qualified name of the resource per module). Is this a WebSphere quirk or am I doing something wrong? I am using WebSphere 8.5.5.3 in a cluster environment.
Here is the bean:
#Singleton
#Startup
public class ConfigSingleton {
#Resource
private String serviceLookup;
}
Here is the ejb-jar.xml:
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>ConfigSingleton</ejb-name>
<env-entry>
<env-entry-name>serviceLookup</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>value</env-entry-value>
</env-entry>
</session>
</enterprise-beans>
</ejb-jar>

You have defined 2 completely different resources; either may be looked up.
Per the Java EE specifications, when you don't use the 'name' attribute of the #Resource annotation a default name is provided for you, which is the fully qualified class name where the annotation exists followed by the JavaBeans property name (which is basically either the name of the field, or the name of the method with 'set' removed and the next character in lowercase). The javadoc for the #Resource annotation is a little misleading as it just says the default is the field name; but does not clarify exactly what the field name is; it is in fact the class name followed by the field name, much like you would see if you printed out the java.lang.reflect.Field that would represent it.
When combining annotations and XML, the XML overrides the annotation only when the 'name' matches. In the sample provided, the names do not match, so you actually have 2 different resources.
If you want your <env-entry> in XML to override the #Resource annotation, so that you can inject a value, then you either need to change your annotation to look like this:
#Resource(name="serviceLookup")
Or change the <env-entry-name> to the fully qualified class name / serviceLookup.
Also, when the EJB module is included in a WAR modules things get a bit more complicated. Not the 'name' aspect, but where you can provide the value. In addition to providing a value in ejb-jar.xml, WebSphere also allows you to provide a value in ibm-ejb-jar-bnd.xml. However, when the EJB modules is in a WAR, then it may also be provided in ibm-web-bnd.xml... since all of the resources for all of the EJBs are visible in the java:comp/env name space for the entire WAR module. So, in the sample, you are getting two different names because of the defaults, and what appears to be two additional copies which are really just provided in case you want to override the values in ibm-web-bnd.xml.

I think what you're seeing here is the different JNDI namespaces:
https://docs.oracle.com/cd/E19798-01/821-1841/girgn/index.html
The resource value can be accessed from within the EJB module using the original name, but if it needs to be accessed from another module within the same application, it should give a JNDI path qualified by the module name, to ensure uniqueness (and traceability), and so on for other applications, and the global namespace.

Related

How to prevent Symfony 4 service override?

I have base /config/services.yaml which stores many services in my Symfony 4.3 project. For example:
My\Namespace\Service:
- '#My\Namespace\Dependency'
For my test purposes, I have config/test/test_services.yaml where I store services with 'test.' prefix to test private services, making them public in test env.
One of the services, declared in test_services.yaml has no prefix. It is identical by its name (FQCN) to another one defined in services.yaml. They have different constructor arguments of the same type.
Test one (/config/test_services.yaml) has mocked dependencies returning fixtures data:
My\Namespace\Service:
- '#My\Namespace\MockedDependency'
Is there a way to prevent service override to not replace mocked service with real one during test execution in test env?
Solution for this situation is create services_test.yaml file and place it under /config folder along with services.yaml.
In that case, symfony will not override service and will use one defined in services_test.yaml during tests execution

Can I add a JNDI Binding with a customized name for inject a Stateless Bean on my client Servlet?

In one hand, I have a Stateless EJB Bean which implements a remote interface.
#Stateless(name = "ejbBean")
#Remote(TimedBean.class)
public class TimedBeanImpl implements TimedBean
...
On the other hand, I have a Servlet client where I need to inject this EJB bean for invoking its operations. The injection referts to a JNDI automatically generated by the server:
public class LoadTimer implements ServletContextListener {
// EAR Local Mapping - EAR Dev Mapping
// #EJB(mappedName = "java:global/appTest/appTestModuleOne-01.00.00/ejbBean")
#EJB(mappedName = "java:global/appTest-01.00.00/appTestModuleOne-01.00.00/ejbBean")
private TimedBean timedBean;
#Override
public void contextInitialized(ServletContextEvent servletcontextevent) {
...
It works.
But the fact of referencing the jndi automatically generated makes the solution highly dependent on the specific environment:
It depends on the server. For example, my local server for testing it's a JBOSS 7.1 and my dev server it's a JBOSS EAP 6.2, and the automatically generated jndi's are different.
It depends on the packaging. Not is the same refers to the ejbBean deploying in a EAR file than in a WAR file.
And it depends on the version of artifacts. More changes.
I want, if possible, is to specify a unique name for the bean can be referred to the servlet in each server, for each version and packaging, in order not to have to be making continuous changes in development and avoid errors in deployments.
Greetings!
You can use <application-name> in application.xml and <module-name> in your module descriptor (web.xml or ejb-jar.xml) to mitigate the hardcoded version numbers. (Note that as of EE 6, you should use #EJB(lookup="...") rather mappedName.) The spec also requires that your application server give you an option to override the lookup name of the #EJB reference while deploying the application, so it should not matter what is hardcoded in your application at development time.

Same stateless bean in two ears

I have the same EJB module with a bean inside an EAR that is server side and an EAR that is the client side.
Can I have this situation?
Because I'm getting this error http://justpaste.it/gfs3
without understand how to fix it.
You have answer in the stack trace:
The short-form default binding 'com.demo.view.RitornaPersonaRemote'
is ambiguous because multiple beans implement the interface :
[RitornaPersonaSenzaClientEAR#RitornaPersonaSenzaClient.jar#RitornaPersona,
RitornaPersonaWebSenzaClientEAR#RitornaPersonaSenzaClient.jar#RitornaPersona].
Provide an interface specific binding or use the long-form default binding on lookup.]
If you are asking whether you may have same EJB jar in multiple project - the answer is yes you can. However during deployment you have to use long-form JNDI, provide different JNDI name for beans in other module or disable short names. You cannot register two beans under same name.
Long name would be in the form RitornaPersonaSenzaClientEAR#RitornaPersonaSenzaClient.jar#com.demo.view.RitornaPersonaRemote
See detailed info here - EJB 3.0 and EJB 3.1 application bindings overview
UPDATE
To disable short names perform the following steps:
Go to Application servers > server1 > Process definition > Java Virtual Machine > Custom properties
Define new custom property com.ibm.websphere.ejbcontainer.disableShortDefaultBindings with value * to disable short bindings for all apps or AppName1|AppName2 to just disable short bindings in selected apps.
Example default bindings are shown in SystemOut.log:
The binding location is: ejblocal:JPADepEar/JPADepEJB.jar/TableTester#ejb.TableTester
The binding location is: ejblocal:ejb.TableTester
The binding location is: java:global/JPADepEar/JPADepEJB/TableTester!ejb.TableTester
And with disableShortDefaultBindings property set there is no short form:
The binding location is: ejblocal:JPADepEar/JPADepEJB.jar/TableTester#ejb.TableTester
The binding location is: java:global/JPADepEar/JPADepEJB/TableTester!ejb.TableTester
There is a bug in the documentation and the correct property is com.ibm.websphere.ejbcontainer.disableShortDefaultBindings not com.ibm.websphere.ejbcontainer.disableShortFormBinding
In my case:- i did install abc.ear and xyz.ear both ear was independent do dependency with each other.
I was calling abc.ear using client-lookup but that was giving me
com.ibm.websphere.naming.CannotInstantiateObjectException: Exception occurred while the JNDI NamingManager was processing a javax.naming.Reference object.
[Root exception is com.ibm.websphere.ejbcontainer.AmbiguousEJBReferenceException: The short-form default binding
'com.ejb.abc' is ambiguous because multiple beans implement the interface :
[xyz-ear#rabc-ejb-1.0.jar#abcInrerfaceImpl, rabc-ear#rabc-ejb-1.0.jar
abcInrerfaceImpl]. Provide an interface specific binding or use the long-form default binding on lookup.]
my Solution was:-
i removed the abc.jar that was inside another application(xyz.ear)
C:\Program Files\IBM\WebSphere\AppServer\profiles\AppSrv01\wstemp\92668751\workspace\cells\mypc00Node01Cell\applications\xyz-ear.ear
'
Then solution client-lookup works fine.
To avoid this in future this is better practice to create separate node on your IBM-WAS server and install both application on different node.
So both application component will not mess up.

Flash Builder Localhost works 100% Remote Host just shows title of Object for every entry

I have finally gotten my Flash Builder to look at my remote services but now I have a problem that my Remote information, which should be the same except for alot more entries, just displays each object with the title [object Object] I have had a look around and I see if I test the service out locally, it is working as it calls all the information under Response Name 'object and Response Value 'Object'
On my localhost configuration this shows the name which is inside my Object items. How can I fix this?
[object Object] is the result of the toString() method of Object. If you get this it probably means your custom object type is being returned as a generic object from the remote AMF service. A lot of things could be the cause of this. Here are a few to check:
1) Make sure that your custom object type is compiled into the app. IF the object is never used explicitly the Flex compiler will not put it in the final SWF. You can do this by creating a fake variable:
private var myUnusedObject : MyCustomObjectType;
Or, I believe, there is a compiler flag to force unused classes to be compiled into the SWF.
2) You may have to add a formal mapping on your server. This depends primarily on what server side tech you're using. In AS3 you add a RemoteAlias metadata to the class. In ColdFusion you use the alias tag on the cfcomponent tag. I believe in WerbORB.NET I had to add the mapping in an XML Config file [but it's been years since I've done that]. I assume alternate technologies use similar approaches.
3) Check case sensitivity on the path names for your server code and make sure that the aliases (mentioned in 2) match.
4) In ColdFusion AMF you have to make sure that your public properties and types match up. They must be in the same order in your AS3 class as they are in your remote CFC. The property types must match. String to String; Boolean to Boolean, etc... I assume other AMF implementations have similar restrictions.

How to access the configuration parameters from the model layer in Symfony 2?

Is there a way to access the configuration parameters in config.yml from the model layer? From the controller I can use $this->container->getParameter('xyz'). But how can it be done from a class in the Model layer?
In symfony2 Entities are designed as POPOs, meaning that they shouldn't really have access to anything outside of their scope.
If you need some config option in one of your entities, consider passing it as a parameter from the controller like so:
$entityName->methodName($param1, $this->container->getParameter('xyz'));
This could (will) break DIC pattern, but you could use a singleton class to "globalize" what you need.
To feed your globals, use bootmethod from Bundle class (where you can access DIC stuff hence configuration).
Or more simple, add a static field to your Entity.
Quick & dirty solution, don't abuse it ;-)
You can use Dependency Injection and add your model to your services.yml file, and like every other service you make you can provide other services as constructor parameters. The only downside is you call $derp = $this->get("your_service_name"); instead of $derp = new Derp();.
For example:
# src/Derp/LolBundle/Resources/config/services.yml
services:
derp:
class: \Derp\LolBundle\Entity\Message
arguments: [#service_container]
#service_container is a service found using php app/console container:debug. It will function identically to $this->container in your controllers and it is provided to the constructor of your class. See here for more information on how to use service containers.
As previously mentioned they are POPOs (Plain Old PHP Objects) and the previous method of dependency injection is poor choice simply because you will have to remember to provide your model entity with the same object every time you use it (which is a hassle) and Symfony2 services are a way to mitigate that pain.

Resources