How to map SQLException from SQL-Object in JDBI3 - jdbi

Lets say I have table defined as:
CREATE TABLE ITEMS(
ID BIGINT PRIMARY KEY,
NAME VARCHAR2,
CONSTRAINT NAME_IS_UNIQUE UNIQUE (NAME)
);
Important part is NAME_IS_UNIQUE constraint.
With corresponding POJO Item as:
class Item{
private Long id;
private String name;
/** getters and setters */
}
And SQL-Object interface with methods defined as:
#SqlUpdate("insert into items(id, name) values(:id, :name)")
int insert(#BindBean Item itemToInsert);
If I'll try to insert into ITEMS with already existing NAME then I will get DB vendor specific SQLException about constraint NAME_IS_UNIQUE violation.
Is there a way to provide mapping between SQLException and application specific Exception (for example ItemNameUniqueConstraintException) so insert method essentially changed it signature to something like the one below?
#SqlUpdate("insert into items(id, name) values(:id, :name)")
int insert(#BindBean Item itemToInsert) throws ItemNameUniqueConstraintException;
Question is not about specific UNIQUE constraint, but more about general case, where SQLException can be about anything: Like referential integrity violation or check constraint violation, etc.

At this moment there is no supported way to handle SQLException -> ApplicationException mapping, you can read discussions and reasoning in the issue.
But you can use workaround with default methods and handle exception manually, e.g.:
class ItemNameUniqueConstraintException extends Exception {
public ItemNameUniqueConstraintException(String message, Throwable cause) {
super(message, cause);
}
}
interface Repository {
default void insert(String name) throws ItemNameUniqueConstraintException {
try {
_insert(name);
} catch (JdbiException e) {
if (e.getCause() instanceof SQLException) {
var cause = (SQLException) e.getCause();
if (cause.getSQLState().equals("11111")) {
throw new ItemNameUniqueConstraintException("Name not unique.", cause);
}
}
// ...
}
}
#SqlUpdate("INSERT INTO test (name) VALUES (:name)")
void _insert(#Bind("name") String name);
}
It is not very pretty, but can be made a little better with separate interfaces for contract of repository and JDBI implementation, which can allow not to expose _insert and similar methods to the caller.

Related

Wso2 XACML get custom attributes

I am using Wso2 IS 5.11.0, I have a requirement where I need to fetch the user attributes by calling web-service based.
Below is the sample attribute finder code:
public class CustomPIPAttributeFinder extends AbstractPIPAttributeFinder {
private static final String PIP_NAME = "CustomPIPAttributeFinder";
private static final Set<String> SUPPORTED_ATTRIBUTES;
private static final Log log = LogFactory.getLog(CustomPIPAttributeFinder.class);
static {
SUPPORTED_ATTRIBUTES = new HashSet<String>();
SUPPORTED_ATTRIBUTES.add(CustomPIPConstants.SAMPLE_ATTRIBUTE_ID);
SUPPORTED_ATTRIBUTES.add(CustomPIPConstants.SAMPLE_ATTRIBUTE_NAME);
SUPPORTED_ATTRIBUTES.add(CustomPIPConstants.SAMPLE_CATEGORY);
}
#Override
public Set<String> getAttributeValues(URI attributeType, URI attributeId, URI category, String issuer,
EvaluationCtx evaluationCtx) throws Exception {
//code
}
private String retrieveSampleName(String accessToken) {
String sampleName = null;
// TODO: Get the value of the sample name from the sampleID from the datasource
return sampleName;
}
/**
* Since we override the {#link #getAttributeValues(URI, URI, URI, String, EvaluationCtx)} this won't be called.
*/
#Override
public Set<String> getAttributeValues(String subject, String resource, String action, String environment,
String attributeId, String issuer) throws Exception {
throw new UnsupportedOperationException("Method unsupported in the context");
}
public void init(Properties properties) throws Exception {
}
public String getModuleName() {
return PIP_NAME;
}
public Set<String> getSupportedAttributes() {
return SUPPORTED_ATTRIBUTES;
}
}
In the sample code we can fetch only one attribute per request.But how can we return multiple attributes before executing policy or get multiple attributes in one request from custom attribute finder. Is there any way to achieve this flow.
As per above code request attribute find(returns only one) in the example it will increase the overhead as for each attribute lookup we are calling web-service every time as it'll increase overhead.

Doctrine 2 custom entity loading and persisting

is it possible to implement a custom hydration and persistence in Doctrine 2 on a per entity basis?
Doctrine 2 has some major limitations regarding value objects (e.g. collections and ids). I wonder if it would be possible to use custom mechanisms (or implementations) for the mapping from object properties to the database (loading and persistence).
I know there are some possibilities to "solve" this problem but I like none of them:
Fake entities require proper handling in the entity which leaks the persistence layer into the domain objects
real entities require a lot more work in persistence (more repositories and more complex handling)
Embaddables have the mentioned limitations
Custom DBAL types with serialization makes querying for certain values impossible or at least extremely slow
I know there are the lifecycle events in doctrine which may be usable. I could't find out if the postLoad event carries an already constructed entity object (with all the VOs)? Becuase in that case it would be useless to me.
best regards,
spigandromeda
Yes, you can register new hydrators in your config/packages/doctrine.yaml like this:
doctrine:
dbal: ...
orm:
hydrators:
CustomEntityHydrator: 'App\ORM\Hydrator\CustomEntityHydrator'
...
mapping: ...
...
You can then use it in your queries like this:
public function findCustomEntities(): array
{
return $this->createQueryBuilder('c')
...your query logic...
->getResult('CustomEntityHydrator');
}
Note, that you can only specify which hydrator you want to use for the root entity. If you fetch associated entities you might end up with a more complicated setup that is hard to debug.
Instead you could consider dealing with value objects (VOs) only in the interface of your entity. In other words, the fields are scalar values, but your method arguments and return values are VOs.
Here is an example with an entity that has a id of type Uuid, a location (some numeric identifier), status (e.g. ternary true/false/null). These are only there to showcase how to deal with different type of value objects:
/**
* #ORM\Entity()
*/
class CustomEntity
{
/**
* #ORM\Id()
* #ORM\Column(type="string", length=64)
*/
private string $id;
/**
* #ORM\Column(type="int")
*/
private int $location;
/**
* #ORM\Column(type="bool, nullable=true)
*/
private bool $status;
private function __construct(Uuid $id, Location $location, Status $status)
{
$this->id = (string) $id;
$this->location = $location->getValue();
$this->status = $status->get();
}
public static function new(Location $location, Status $status): self
{
return new self(Uuid::v4(), $location, $status);
}
public function getId(): Uuid
{
return Uuid::fromString($this->id);
}
public function getLocation(): Location
{
return new Location($this->location);
}
public function activate(): void
{
$this->status = true;
}
public function deactivate(): void
{
$this->status = false;
}
public function isActive(): bool
{
$this->status === true;
}
public function isInactive(): bool
{
$this->status === false;
}
public function isUninitialized(): bool
{
$this->status === null;
}
public function getStatus(): Status
{
if ($this->status === null) {
return new NullStatus();
}
if ($this->status === true) {
return new ActiveStatus();
}
return new InactiveStatus();
}
}
As you can see, you could replace new() with a public constructor. It would work similar with setters. I sometimes even use (private) setters for this in the constructor. In case of the status you don't even need setters if you instead use multiple methods that set the value internally. Similarly you might want to return scalar values instead of a VO in some cases (or the other way around as shown with the status getter and issers).
The point is, your entity looks from the outside as if it would use your VOs, but internally it already switches to a representation that works better with Doctrine ORM. You could even mix this with using VOs and custom types, e.g. for the UUID. You just have to be careful, when your VO needs more info for being constructed than you want to store in the database, e.g. if the numeric location in our example would also use a locale during creation, then we would need to store this (which makes sense as it seems to be related to the numeric id) or we have to hardcode it in the entity or add an abstraction above, that has access to the locale, in which case your entity would likely not return a Location or at least not a LocalizedLocation.
You might also want to consider not having a VO for each and every property in your entity. While it definitely can be helpful, e.g. to wrap an Email into a custom VO to ensure validity instead of just type hinting for string, it might be less useful for something as generic as a (user's) name, which should be very lenient with which strings it accepts as there are a wide variety of names. Using the approach above you can easily introduce a VO later, by adding a new getter for the VO, changing new() or any other method that mutates your property and then not having to change anything in the data model below (unless there is a more drastic change to how the value is represented).

Recommended Access Modifiers for Testability of Wrapper Methods

One thing I have started doing in my tests is to wrap error messages and string concatenations into methods or variables to keep my tests robust should the error message contents change later.
So for example, I would refactor something like this:
try{
someMethod();
}catch(e){
throw new Error('error message.');
}
into this:
let errorMessage = 'error message';
...
try{
someMethod();
}catch(e){
throw new Error(errorMessage);
}
Or something similar if the error message contains a variable or something.
My question is what would be the best way to do this in Typescript? In Java I would have them be package-protected, but here it seems Jasmine does not have access to methods like this if they are protected. I have also tried making them static.
Is there preferred method for this?
This is one occasion where you can transfer some good practices from other languages.
If you create custom exceptions, you can test their type, rather than the strings - and you can also ensure uniformity of error messages.
This example looks a bit convoluted, but it should give you an idea (adapted from page 163-168 Pro Typescript).
A base CustomException class is created that implements the Error interface and will sit beneath any custom error types we want in our application.
An InvalidDateException is created to represent a particular class of error, this is the only place the error message string needs to be stored in the application.
You can now look at particular kinds of error as in the example catch statement where instanceof is used to check the type.
All your custom exceptions are compatible with the Error interface, which required name and toString().
Code:
class CustomException implements Error {
protected name = 'CustomException';
constructor(public message: string) {
}
toString() {
return this.name + ': ' + this.message;
}
}
class InvalidDateException extends CustomException {
constructor(public date: Date) {
super('The date supplied was not valid: ' + date.toISOString());
this.name = 'InvalidDateException';
}
}
try {
throw new InvalidDateException(new Date());
} catch (ex) {
if (ex instanceof InvalidDateException) {
alert(ex.toString());
}
}

Java CXF: What is the best way to handle Common Objects under different packages or namespaces?

We're integrating with a 3rd Party webservice by using Wsdl2Java to translate their Schema and endpoints into Java for three different webservices that they offer.
This particular provider uses a lot of the same objects (think objects representing an Address, Money, Weight, etc), but, in their infinite wisdom, they've decided to create a different namespace for each webservice and duplicate the definition of their schemas for each one. The result is you have the following classes output for CXF integration:
com.thirdpartyguys.api.firstApi.Money
com.thirdpartyguys.api.secondApi.Money
com.thirdpartyguys.api.thirdApi.Money
Translating our data into theirs can involve a lot of business logic and, as a result, we have to define the code that creates the objects in triplicate for each individual Webservice API.
To overcome this problem I created an Interface defined thusly:
import org.apache.commons.beanutils.BeanUtils;
public interface CommonObjectInterface<A, R, S> {
A toFirstApi();
R toSecondApi();
S toThirdApi();
default Object doTransform(Object destination, Object source) {
try {
BeanUtils.copyProperties(destination, source);
} catch (Exception e) {
throw new RuntimeException("Fatal error transforming Object", e);
}
return destination;
}
}
You would then have each common object implement the interface, define its own constructors, fluent API, etc, and call the toXXX() methods to get the proper form of the object for the respective API.
Right now most of these implementing classes work by keeping a copy of one of the Apis locally, setting data on that, and then transforming it for the proper API using the doTransform() method which in its default form uses the Apache Commons BeanUtils.copyProperties() method.
It's more elegant than having the same code exist in three different places, but not by much! There's a lot of boilerplate and, even though this won't be getting hammered too much, not that efficient.
I would like to get feedback from the community as to whether this is a good idea or if there are better approaches. A similar question was asked years ago here, but I don't know if better solutions have emerged since it was asked. I imagine the best thing would be configuring wsdl2Java to allow setting the namespace at runtime, but from my initial research this does not seem to be possible.
The solution to this problem is specific to this exact situation:
1) A webservice provider that has the same object in different namespaces
2) Using wsdl2Java or some underlying Apache CXF technology to generate the web artifacts for writing a client.
This is a fringe case so I'm not sure how helpful this will be to the community but the trick is to account for a few situations where a copyProperties method doesn't work. In this case I'm using Spring's BeanUtils and BeanWrapper classes although I'm sure this could be adapted for Apache as well. The following code does the trick:
final String TARGET_PACKAGE = "com.thirdpartyguys.api";
public Object doTransform(Object destination, Object source) {
/*
* This will copy all properties for the same data type for which there is a getter method in
* source, and a setter method in destination
*/
BeanUtils.copyProperties(source, destination);
BeanWrapper sourceWrapper = new BeanWrapperImpl(source);
for(PropertyDescriptor p : sourceWrapper.getPropertyDescriptors()) {
/*
* Properties that are references to other schema objects are identical in structure, but have
* different packages. We need to copy these separately
*/
if(p.getPropertyType().getPackage().getName().startsWith(TARGET_PACKAGE)) {
try {
commonPropertyCopy(destination, source, p);
} catch (Exception e) {
throw new RuntimeException("Fatal error creating Data", e);
}
}
/*
* Properties that reference list don't create setters according to the Apache CXF
* convention. We have to call the get method and addAll()
*/
else if(Collection.class.isAssignableFrom(p.getPropertyType())) {
try {
collectionCopy(destination, source, p);
} catch (Exception e) {
throw new RuntimeException("Fatal error creating Data", e);
}
}
}
return destination;
}
private void collectionCopy(Object destination, Object source, PropertyDescriptor sourceProperty) throws Exception {
BeanWrapper destWrapper= new BeanWrapperImpl(destination);
PropertyDescriptor destProperty = destWrapper.getPropertyDescriptor(sourceProperty.getName());
Collection<?> sourceCollection = (Collection<?>) sourceProperty.getReadMethod().invoke(source);
Collection<Object> destCollection = (Collection<Object>) destProperty.getReadMethod().invoke(destination);
destCollection.addAll(sourceCollection);
}
private void commonPropertyCopy(Object destination, Object source, PropertyDescriptor sourceProperty) throws Exception {
if(sourceProperty.getPropertyType().isEnum()) {
instantiateEnum(destination, source, sourceProperty);
}
else {
instantiateObject(destination, source, sourceProperty);
}
}
private void instantiateEnum(Object destination, Object source, PropertyDescriptor sourceProperty) throws Exception {
BeanWrapper destWrapper= new BeanWrapperImpl(destination);
Enum<?> sourceEnum = (Enum<?>) sourceProperty.getReadMethod().invoke(source);
PropertyDescriptor destProperty = destWrapper.getPropertyDescriptor(sourceProperty.getName());
Object enumValue = Enum.valueOf(destProperty.getPropertyType().asSubclass(Enum.class), sourceEnum.name());
destProperty.getWriteMethod().invoke(destination, enumValue);
}
private void instantiateObject(Object destination, Object source, PropertyDescriptor sourceProperty) throws Exception {
Object subObj = sourceProperty.getReadMethod().invoke(source);
if(subObj!=null) {
BeanWrapper destWrapper = new BeanWrapperImpl(destination);
String subObjName = sourceProperty.getName();
PropertyDescriptor destProperty = destWrapper.getPropertyDescriptor(subObjName);
Class<?> propertyType = destProperty.getReadMethod().getReturnType();
Object subObjCopy = propertyType.getConstructor().newInstance();
doTransform(subObjCopy, subObj);
destProperty.getWriteMethod().invoke(destination, subObjCopy);
}
}
instantiateObject is used to create new instances of the "identical" objects from different packages. This also applies for Enumerated types and requires its own method, hence the implementation of instantiateEnum. Finally, the default CXF implemenation offers no setter method for Lists. We handle this situation in collectionCopy.

Acceleo invoking Java Service wrapping an OCLHelper

I need to get the OCL model of conditions contained in UML edges from an ACCELEO script navigating the main UML model. To this end I have defined the following Java class:
public class GetOCLModel {
public Constraint getOCLModel(Classifier context, String expression){
OCL<Package, Classifier, Operation, Property, EnumerationLiteral, Parameter,
State, CallOperationAction, SendSignalAction, Constraint, Class, EObject> ocl;
//CL.newInstance(EcoreEnvironmentFactory.INSTANCE);
UMLEnvironmentFactory uef = new UMLEnvironmentFactory();
ocl = OCL.newInstance(uef.createEnvironment());
OCLHelper<Classifier, Operation, Property, Constraint> helper = ocl.createOCLHelper();
helper.setContext(context);
Constraint expr= null;
try {
expr= (Constraint) helper.createInvariant(expression);
System.out.println("Hunky Dory!");
} catch (ParserException e) {
e.printStackTrace();
}
return expr;
}
}
This is the ACCELEO Module wrapping it:
[module generateOclModel('http://www.eclipse.org/ocl/1.1.0/UML','http://www.eclipse.org/uml2/2.1.0/UML')/]
[query public getOclModel(cl:Classifier, str:String): Constraint = invoke('sfg.baleno.src.services.GetOCLModel',
'getOCLModel(org.eclipse.uml2.uml.Classifier, java.lang.String)',Sequence{cl,str}) /]
And here is how I am trying to invoke it from the main ACCELEO module:
[c.getOclModel('self.name=\'Testclass\'')._context.name/]
It does not work and I cant' see why, any idea?
UPDATE
I realized the helper was actually outputting this exception
org.eclipse.ocl.SemanticException: Unrecognized variable: (name)
what am I doing wrong?