Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EJBCLIENT-185] Helper factory methods for objects with generic type parameters #189

Merged
merged 4 commits into from
Jan 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/org/jboss/ejb/_private/Logs.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ public interface Logs extends BasicLogger {
@Message(id = 66, value = "Operation interrupted")
EJBException operationInterrupted();

@Message(id = 67, value = "Cannot convert %s to stateful")
IllegalArgumentException cannotConvertToStateful(EJBLocator<?> locator);

// Proxy API errors

@Message(id = 100, value = "Object '%s' is not a valid proxy object")
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/jboss/ejb/client/AbstractEJBMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import javax.ejb.EJBObject;

import org.jboss.ejb._private.Logs;
import org.wildfly.common.Assert;

/**
* Abstract base class for all EJB metadata.
Expand All @@ -43,6 +44,8 @@ public abstract class AbstractEJBMetaData<T extends EJBObject, H extends EJBHome
private final EJBHomeLocator<H> homeLocator;

AbstractEJBMetaData(final Class<T> remoteInterfaceClass, final EJBHomeLocator<H> homeLocator) {
Assert.checkNotNullParam("remoteInterfaceClass", remoteInterfaceClass);
Assert.checkNotNullParam("homeLocator", homeLocator);
this.remoteInterfaceClass = remoteInterfaceClass;
this.homeLocator = homeLocator;
}
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/org/jboss/ejb/client/EJBHandle.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,14 @@ public EJBHandle(final EJBLocator<T> locator) {
this.locator = locator;
}

static <T extends EJBObject> EJBHandle<T> handleFor(EJBLocator<T> locator) {
/**
* Construct a new instance.
*
* @param locator the locator for the EJB instance (must not be {@code null})
* @param <T> the EJB object type
* @return the handle (not {@code null})
*/
public static <T extends EJBObject> EJBHandle<T> create(EJBLocator<T> locator) {
return new EJBHandle<>(locator);
}

Expand Down
9 changes: 8 additions & 1 deletion src/main/java/org/jboss/ejb/client/EJBHomeHandle.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,14 @@ public EJBHomeHandle(final EJBHomeLocator<T> locator) {
this.locator = locator;
}

static <T extends EJBHome> EJBHomeHandle<T> handleFor(EJBHomeLocator<T> locator) {
/**
* Construct a new instance.
*
* @param locator the locator for the home interface (must not be {@code null})
* @param <T> the EJB home type
* @return the handle (not {@code null})
*/
public static <T extends EJBHome> EJBHomeHandle<T> create(EJBHomeLocator<T> locator) {
return new EJBHomeHandle<>(locator);
}

Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/jboss/ejb/client/EJBHomeLocator.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,19 @@ public EJBHomeLocator(final EJBHomeLocator<T> original, final Affinity newAffini
super(original, newAffinity);
}

/**
* Construct a new instance.
*
* @param viewType the view type (must not be {@code null})
* @param identifier the EJB identifier (must not be {@code null})
* @param affinity the affinity
* @param <T> the remote view type
* @return the new instance (not {@code null})
*/
public static <T extends EJBHome> EJBHomeLocator<T> create(final Class<T> viewType, final EJBIdentifier identifier, final Affinity affinity) {
return new EJBHomeLocator<T>(viewType, identifier, affinity);
}

public EJBHomeLocator<T> withNewAffinity(final Affinity affinity) {
Assert.checkNotNullParam("affinity", affinity);
return getAffinity().equals(affinity) ? this : new EJBHomeLocator<T>(this, affinity);
Expand Down
57 changes: 57 additions & 0 deletions src/main/java/org/jboss/ejb/client/EJBIdentifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
import org.wildfly.common.Assert;

/**
* An identifier for an EJB located within a container. This identifier only names the EJB; it does not specify
* a view, which must be done using the {@link EJBLocator} family of types.
* <p>
* EJB identifiers are suitable for use as hash keys.
*
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
*/
public final class EJBIdentifier implements Serializable {
Expand All @@ -39,37 +44,79 @@ public final class EJBIdentifier implements Serializable {
private final String distinctName;
private transient int hashCode;

/**
* Construct a new instance.
*
* @param appName the application name (must not be {@code null})
* @param moduleName the module name (must not be {@code null} or empty)
* @param beanName the bean name (must not be {@code null} or empty)
* @param distinctName the distinct name (must not be {@code null})
*/
public EJBIdentifier(final String appName, final String moduleName, final String beanName, final String distinctName) {
Assert.checkNotNullParam("appName", appName);
Assert.checkNotNullParam("moduleName", moduleName);
Assert.checkNotEmptyParam("moduleName", moduleName);
Assert.checkNotNullParam("beanName", beanName);
Assert.checkNotEmptyParam("beanName", beanName);
Assert.checkNotNullParam("distinctName", distinctName);
this.appName = appName;
this.moduleName = moduleName;
this.beanName = beanName;
this.distinctName = distinctName;
}

/**
* Get the application name, which may be empty.
*
* @return the application name (not {@code null})
*/
public String getAppName() {
return appName;
}

/**
* Get the module name.
*
* @return the module name (not {@code null})
*/
public String getModuleName() {
return moduleName;
}

/**
* Get the bean name.
*
* @return the bean name (not {@code null})
*/
public String getBeanName() {
return beanName;
}

/**
* Get the distinct name.
*
* @return the distinct name (not {@code null})
*/
public String getDistinctName() {
return distinctName;
}

/**
* Determine if this EJB identifier is equal to the given object.
*
* @param other the object to test
* @return {@code true} if the object is equal to this one, {@code false} otherwise
*/
public boolean equals(final Object other) {
return other instanceof EJBIdentifier && equals((EJBIdentifier) other);
}

/**
* Determine if this EJB identifier is equal to the given object.
*
* @param other the object to test
* @return {@code true} if the object is equal to this one, {@code false} otherwise
*/
public boolean equals(final EJBIdentifier other) {
return other != null && (
other == this ||
Expand All @@ -81,6 +128,11 @@ public boolean equals(final EJBIdentifier other) {
);
}

/**
* Get the hash code of this identifier.
*
* @return the hash code of this identifier
*/
public int hashCode() {
int hashCode = this.hashCode;
if (hashCode != 0) {
Expand All @@ -90,6 +142,11 @@ public int hashCode() {
return this.hashCode = hashCode == 0 ? 1 : hashCode;
}

/**
* Get the EJB identifier as a human-readable string.
*
* @return the EJB identifier as a human-readable string (not {@code null})
*/
public String toString() {
final String distinctName = getDistinctName();
if (distinctName == null || distinctName.isEmpty()) {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/jboss/ejb/client/EJBInvocationHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,12 @@ Object invoke(final Object proxy, final EJBProxyInformation.ProxyMethodInfo meth
}
case EJBProxyInformation.MT_GET_HANDLE: {
// TODO: cache instance
return EJBHandle.handleFor(locatorRef.get().narrowTo(EJBObject.class));
return EJBHandle.create(locatorRef.get().narrowTo(EJBObject.class));
}
case EJBProxyInformation.MT_GET_HOME_HANDLE: {
if (locatorRef.get() instanceof EJBHomeLocator) {
// TODO: cache instance
return EJBHomeHandle.handleFor(locatorRef.get().narrowAsHome(EJBHome.class));
return EJBHomeHandle.create(locatorRef.get().narrowAsHome(EJBHome.class));
}
throw new RemoteException("Cannot invoke getHomeHandle() on " + proxy);
}
Expand Down Expand Up @@ -322,7 +322,7 @@ void setSessionID(final SessionID sessionID) {
}
throw Logs.MAIN.ejbIsAlreadyStateful();
}
newVal = new StatefulEJBLocator<T>(oldVal, sessionID);
newVal = oldVal.withSession(sessionID);
} while (! locatorRef.compareAndSet(oldVal, newVal));
}

Expand Down
24 changes: 24 additions & 0 deletions src/main/java/org/jboss/ejb/client/EJBLocator.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import javax.ejb.EJBHome;
import javax.ejb.EJBObject;

import org.jboss.ejb._private.Logs;
import org.wildfly.common.Assert;

/**
Expand Down Expand Up @@ -114,6 +115,29 @@ public abstract class EJBLocator<T> implements Serializable {
*/
public abstract EJBLocator<T> withNewAffinity(Affinity affinity);

/**
* Create a copy of this locator, but with the given stateful session ID. If this locator cannot be converted,
* an exception is thrown.
*
* @param sessionId the stateful session ID (must not be {@code null})
* @return the new locator (not {@code null})
*/
public StatefulEJBLocator<T> withSession(SessionID sessionId) {
throw Logs.MAIN.cannotConvertToStateful(this);
}

/**
* Create a copy of this locator, but with the given affinity and stateful session ID. If this locator cannot be converted,
* an exception is thrown.
*
* @param sessionId the stateful session ID (must not be {@code null})
* @param affinity the new affinity (must not be {@code null})
* @return the new locator (not {@code null})
*/
public StatefulEJBLocator<T> withSessionAndAffinity(SessionID sessionId, Affinity affinity) {
throw Logs.MAIN.cannotConvertToStateful(this);
}

/**
* Determine whether a {@link #narrowTo(Class)} operation would succeed.
*
Expand Down
20 changes: 5 additions & 15 deletions src/main/java/org/jboss/ejb/client/EJBMetaDataImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,28 +75,18 @@ public EJBMetaDataImpl(AbstractEJBMetaData<?, ?> ejbMetaData) {
}

public AbstractEJBMetaData<?, ?> toAbstractEJBMetaData() {
final EJBHomeLocator<? extends EJBHome> homeLocator = EJBClient.getLocatorFor(home).narrowAsHome(homeClass);
final Class<? extends EJBObject> ejbObjectClass = remoteClass.asSubclass(EJBObject.class);
if (session || statelessSession) {
if (statelessSession) {
return createStatelessMetaData(remoteClass.asSubclass(EJBObject.class), homeClass, home);
return StatelessEJBMetaData.create(ejbObjectClass, homeLocator);
}
return createStatefulMetaData(remoteClass.asSubclass(EJBObject.class), homeClass, home);
return StatefulEJBMetaData.create(ejbObjectClass, homeLocator);
} else {
return createEntityMetaData(remoteClass.asSubclass(EJBObject.class), homeClass, home, pkClass);
return EntityEJBMetaData.create(ejbObjectClass, homeLocator, pkClass);
}
}

private static <T extends EJBObject, H extends EJBHome> StatelessEJBMetaData<T, ? extends H> createStatelessMetaData(Class<T> remoteClass, Class<H> homeClass, EJBHome home) {
return new StatelessEJBMetaData<>(remoteClass, EJBClient.getLocatorFor(home).<H>narrowAsHome(homeClass));
}

private static <T extends EJBObject, H extends EJBHome> StatefulEJBMetaData<T, ? extends H> createStatefulMetaData(Class<T> remoteClass, Class<H> homeClass, EJBHome home) {
return new StatefulEJBMetaData<>(remoteClass, EJBClient.getLocatorFor(home).<H>narrowAsHome(homeClass));
}

private static <T extends EJBObject, H extends EJBHome> EntityEJBMetaData<T, ? extends H> createEntityMetaData(Class<T> remoteClass, Class<H> homeClass, EJBHome home, Class<?> pkClass) {
return new EntityEJBMetaData<>(remoteClass, EJBClient.getLocatorFor(home).<H>narrowAsHome(homeClass), pkClass);
}

/**
* Obtains the home interface of the enterprise Bean.
*/
Expand Down
11 changes: 4 additions & 7 deletions src/main/java/org/jboss/ejb/client/EJBRootContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,18 @@ protected Object lookupNative(final Name name) throws NamingException {
throw Logs.MAIN.lookupFailed(name, name, e);
}
EJBLocator<?> locator;
final EJBIdentifier identifier = new EJBIdentifier(appName, moduleName, beanName, distinctName);
if (stateful) {
try {
locator = EJBClient.createSession(affinity, view, appName, moduleName, beanName, distinctName);
locator = EJBClient.createSession(StatelessEJBLocator.create(view, identifier, affinity));
} catch (Exception e) {
throw Logs.MAIN.lookupFailed(name, name, e);
}
if (locator == null) {
throw Logs.MAIN.nullSessionCreated(name, name, affinity, new EJBIdentifier(appName, moduleName, beanName, distinctName));
throw Logs.MAIN.nullSessionCreated(name, name, affinity, identifier);
}
} else {
locator = createLocator(view, appName, moduleName, beanName, distinctName);
locator = StatelessEJBLocator.create(view, identifier, affinity);
}
return EJBClient.createProxy(namingProvider, locator);
}
Expand All @@ -165,10 +166,6 @@ private static ClassLoader doGetContextClassLoader() {
return Thread.currentThread().getContextClassLoader();
}

private <T> StatelessEJBLocator<T> createLocator(Class<T> viewType, String appName, String moduleName, String beanName, String distinctName) {
return new StatelessEJBLocator<T>(viewType, appName, moduleName, beanName, distinctName, affinity);
}

protected Object lookupLinkNative(final Name name) throws NamingException {
return lookupNative(name);
}
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/jboss/ejb/client/EntityEJBLocator.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ public EntityEJBLocator(final EntityEJBLocator<T> original, final Affinity newAf
this.primaryKey = original.primaryKey;
}

/**
* Construct a new instance.
*
* @param viewType the view type (must not be {@code null})
* @param identifier the EJB identifier (must not be {@code null})
* @param primaryKey the entity primary key (must not be {@code null})
* @param affinity the affinity
* @param <T> the remote view type
* @return the new instance (not {@code null})
*/
public static <T extends EJBObject> EntityEJBLocator<T> create(final Class<T> viewType, final EJBIdentifier identifier, final Object primaryKey, final Affinity affinity) {
return new EntityEJBLocator<T>(viewType, identifier, primaryKey, affinity);
}

public EntityEJBLocator<T> withNewAffinity(final Affinity affinity) {
Assert.checkNotNullParam("affinity", affinity);
return getAffinity().equals(affinity) ? this : new EntityEJBLocator<T>(this, affinity);
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/org/jboss/ejb/client/EntityEJBMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import javax.ejb.EJBHome;
import javax.ejb.EJBObject;

import org.wildfly.common.Assert;

/**
* EJB metadata for entity EJBs.
*
Expand All @@ -48,9 +50,24 @@ public final class EntityEJBMetaData<T extends EJBObject, H extends EJBHome> ext
*/
public EntityEJBMetaData(final Class<T> remoteInterfaceClass, final EJBHomeLocator<H> homeLocator, final Class<?> primaryKeyClass) {
super(remoteInterfaceClass, homeLocator);
Assert.checkNotNullParam("primaryKeyClass", primaryKeyClass);
this.primaryKeyClass = primaryKeyClass;
}

/**
* Construct a new instance.
*
* @param remoteInterfaceClass the remote interface class (must not be {@code null})
* @param homeLocator the EJB home locator (must not be {@code null})
* @param primaryKeyClass the primary key class (must not be {@code null})
* @param <T> the remote interface type
* @param <H> the home interface type
* @return the new instance (not {@code null})
*/
public static <T extends EJBObject, H extends EJBHome> EntityEJBMetaData<T, H> create(final Class<T> remoteInterfaceClass, final EJBHomeLocator<H> homeLocator, final Class<?> primaryKeyClass) {
return new EntityEJBMetaData<T, H>(remoteInterfaceClass, homeLocator, primaryKeyClass);
}

public boolean isSession() {
return false;
}
Expand Down
Loading