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.
Related
We have a DynamoDB table Test which has an attribute Template. Bellow are the class definitions. I would like to update the Template attribute or some of its attribute based on certain condition. I tried doing the same using UpdateItemRequest but unable to find a way to update the template attribute since everything is converted to either string, number or bytes.
Code for reference.
#DynamoDbBean
public class Test implements NoSQLEntity {
private String name;
private Template template;
#DynamoDbAttribute("name")
public String getName() {
return name;
}
#DynamoDbAttribute("template")
public Template getTemplate() {
return template;
}
}
#DynamoDbBean
public class Template {
private String pk;
private String name;
private List<String> demo;
#DynamoDbAttribute("pk")
public String getPk() {
return this.pk;
}
#DynamoDbAttribute("name")
public String getName() {
return name;
}
#DynamoDbAttribute("demo")
public List<String> getdemo() {
return demo;
}
}
Sample update code:
UpdateItemRequest request = UpdateItemRequest.builder()
.tableName("Test")
.key(itemKey)
.updateExpression("SET tmpt = :tmt")
.expressionAttributeValues(expressionValues)
.build();
Here I am unable to build the :tmt using the AttributeValue. Can someone please guide me?
Here is a Readme from the Eng team that you may find useful:
https://github.com/aws/aws-sdk-java-v2/tree/master/services-custom/dynamodb-enhanced
DynamoDb Enhanced provides DefaultAttributeConverterProvider that will identify a converter that can convert the specific Java type into the AttrbuteValue type that can used to update the item.
Smaple Code:
AttributeValue value = DefaultAttributeConverterProvider.create()
.converterFor(EnhancedType.documentOf(Template.class,
TableSchema.fromBean(Template.class)))
.transformFrom(template);
Can then put this value in the expressionValues map.
Map<String, AttributeValue> expressionValues = new HashMap<>();
expressionValues.put(":tmt", value);
UpdateItemRequest request = UpdateItemRequest.builder()
.tableName("Test")
.key(itemKey)
.updateExpression("SET tmpt = :tmt")
.expressionAttributeValues(expressionValues)
.build();
I need to retrieve data from the db, via a service, in order to test captured data for structural validity.
i.e. The db data specifies the sizes of parts of a captured concatenated string, (in a certain order), which I mock. So no worries there.
But I don't want to mock the service's data.
I want to actually retrieve the db data, which can change/vary vastly for different clients, and different scenarios, or be changed regularly.
So, changing the mocked data for each scenario is not feasible.
The Service implements an interface and also injects the Data Access Layer's interface.
I do set 'CallBase' as true, but I'm not getting db Data back.
Please help.
Thanks
public interface I_PartDao
{
ExBool List(out List<GXL_PartSizes> _PartSizes);
}
public class GXL_PartSizes
{
public int? ID { get; set; }
public int? PartLength { get; set; }
public int? SortOrder { get; set; }
public GXL_PartSizes()
{
this.ID = null;
this.PartLength = null;
this.SortOrder = null;
}
}
// Service Layer
public interface I_PartBo
{
ExBool List(out List<GXL_PartSizes> _PartSizes);
}
public class PartBo : I_PartBo
{
// For the injection of the Dao services (Dao handles the Ado CRUD operations against MSSQL dbase)
private I_PartDao PartDao;
public PartBo(I_PartDao dao_Part)
{
this.PartDao = dao_Part ?? throw new ArgumentNullException("dao_Part");
}
public ExBool List(out List<GXL_PartSizes> _PartSizes)
{
return this.PartDao.List(out _PartSizes);
}
}
[TestClass]
public class GXL_ConcatenatedStructures_Test
{
ExBool result = new ExBool(); // A class to handle error messages and statuses
private List<GXL_PartSizes> partSizes;
[TestMethod]
public void Test_Part_1_Length_matches_dbStructure_for_part1()
{
// Arrange
var mockService = new Mock<I_PartBo>();
// This is retrieved from the data posted back to the controller,..but for here and now, just a local populated strign var
var concatenatedString_part1 = "ABC";
// Act
//mockService.CallBase = true;
mockService
.Setup(x => x.List(out partSizes))
.Returns(result);
// Assert
Assert.AreEqual(concatenatedString_part1, partSizes[0].PartLength);
}
}
I thought that there was a way to do what I wanted to, by using moq.
However,
by just using the normal concrete classes, as per the usual (sans DI) way, The db data is retrieved.
i.e.
NamespaceX.GLX_SetupDao dao = new NamespaceX.GLXSetupDao("data source=LAPTOP-a; Initial
Catalog=aaaa; Integrated Security=True;");
GLX_SetupBo boService = new GLX_SetupBo(dao);
result = boService.List(out List<GXL_PartSizes> sizes);
I have a class called Product which has a property called id of type long. Below is the class
public class Product {
private long id;
}
The value of id is beyond the value which javascript can handle. I realized this after seeing the below link
Parse json in javascript - long numbers get rounded
I dont want to declare the field as String in the domain class. But I want to say to RestEasy that it has to send the value as a string in the json response.
How can I do this? I dont want to use any third party api. Is it possible in RestEasy. I have gone through the documentation but did not find any such annotation or may be I did not go through the documentation properly.
Can anyone please help. Thanks all in advance.
If you are using Jackson as JSON Serializer you can extend the JacksonJsonProvider:
#Provider
public class JsonProvider extends org.codehaus.jackson.JacksonJsonProvider {
public JsonProvider() {
ObjectMapper objectMapper = locateMapper(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE);
objectMapper.configure(org.codehaus.jackson.JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
}
}
If you are using Jettison you can register a custom XmlAdapter:
public class LongAdapter extends XmlAdapter<String, Long> {
#Override
public String marshal(Long id) throws Exception {
if (id == null) {
return "";
}
return id.toString();
}
#Override
public Long unmarshal(String id) throws Exception {
return Long.parseLong(id);
}
}
I'm relatively new to JavaEE and web services, however, I'm using netbeans to generate my client and webservice resources. I have a resource "CustomerData" that represents a mysql database table and a value "rewardsPoints" representing a column in that table, however, I am unable to update the value due to a ConstraintViolationException, specifically:
javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'preUpdate'. Please refer to embedded ConstraintViolations for details.
I'm not familiar with the 'preUpdate' callback event, is it something I need to override? I can't seem to figure out exactly why this exception is being thrown, but, as I said, i'm very new to web service programming. Here are my classes:
#Stateless
#Path("customers")
public class CustomerDataFacadeREST extends AbstractFacade<CustomerData> {
#PersistenceContext(unitName = "CustomerPortalPU")
private EntityManager em;
public CustomerDataFacadeREST() {
super(CustomerData.class);
}
#PUT
#Path("{id}")
#Consumes({"application/xml", "application/json"})
public void edit(#PathParam("id") Integer id, CustomerData entity) {
super.edit(entity);
}
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public CustomerData find(#PathParam("id") Integer id) {
return super.find(id);
}
#GET
#Path("addPoints/{id}/{amount}")
#Produces({"text/plain"})
public String addPoints(#PathParam("id") Integer id, #PathParam("amount") int amount) {
CustomerData customer = find(id);
customer.getRewardsPoints(customer.getRewardsPoints() + amount);
em.persist(customer);
edit(customer);
return customer.getRewardsPoints();
}
#Override
protected EntityManager getEntityManager() {
return em;
}
}
And the CustomerData entity class:
#Entity
#Table(name = "tbl_customer_data")
#XmlRootElement
public class CustomerData implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Column(name = "rewards_points")
private int rewardsPoints;
public CustomerData(Integer id, int rewardsPoints) {
this.id = id;
this.rewardsPoints = rewardsPoints;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public int getRewardsPoints() {
return rewardsPoints;
}
public void setRewardsPoints(int rewardsPoints) {
this.rewardsPoints = rewardsPoints;
}
}
When I try to access the URI:
http://localhost:8080/CustomerPortal/ws/customers/addPoints/1/5
to add 5 points to user with id 1 i get an HTTP 500 error and in the glassfish logs it says
[2013-11-05T03:28:11.733-0500] [glassfish 4.0] [WARNING] [ejb.system_exception] [javax.enterprise.system.container.ejb.com.sun.ejb.containers] [tid: _ThreadID=21 _ThreadName=http-listener-1(3)] [timeMillis: 1383640091733] [levelValue: 900] [[
EJB5184:A system exception occurred during an invocation on EJB CustomerDataFacadeREST, method: public java.lang.String com.webservice.entities.CustomerDataFacadeREST.addPoints(java.lang.Integer,int)]]
[2013-11-05T03:28:11.741-0500] [glassfish 4.0] [WARNING] [] [javax.enterprise.web] [tid: _ThreadID=21 _ThreadName=http-listener-1(3)] [timeMillis: 1383640091741] [levelValue: 900] [[
StandardWrapperValve[com.webservice.entities.ApplicationConfig]: Servlet.service() for servlet com.webservice.entities.ApplicationConfig threw exception
javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'preUpdate'. Please refer to embedded ConstraintViolations for details.
Any resources, insight or information regarding this issue would be extremely helpful.
The exception has little to do with web services: it has to do with Bean Validation instead.
In this case, since the Validation fails inside method addPoints (look at the stack trace) the only line that can cause it is when persisting or editing an Entity of type CustomerData. The only constraint you have in that class is that rewardsPoints should not be null. So, that's the cause of the exception.
However there some things that won't work in addPoints method:
You should check that find() method doesn't return a null object.
customer.getRewardsPoints(customer.getRewardsPoints() + amount) never sets the property (does it compile?)
EntityManager.persist() throws exception if the entity already exists. You probably want to remove that line if you only want to edit (update) the entity.
Note: I am not sure that the code you have posted is really compiling and causing that exception. That's probably caused by another version.
According to the documentation, you should be able to pass a javabean to a FreeMarker template, and it will be able to access the getters of the bean. I've been trying to do this, but have not had any luck. Here's my code where I pass the bean to the template.
public class Hello extends HttpServlet {
public static final Logger LOGGER = Logger.getLogger(Hello.class.getName());
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
Configuration cfg = new Configuration();
cfg.setDirectoryForTemplateLoading(new File(this.getServletContext().getRealPath("/templates")));
cfg.setObjectWrapper(new DefaultObjectWrapper());
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
cfg.setIncompatibleImprovements(new Version(2, 3, 20)); // FreeMarker 2.3.20
final String name = req.getParameter("name");
// This works when model is a Map, but not when it is a bean
Model model = new Model();
model.setUsername(name);
Template template = cfg.getTemplate("hello.ftl");
template.process(model, resp.getWriter());
} catch (TemplateException ex) {
LOGGER.log(Level.SEVERE, "Unexpected template exception", ex);
resp.sendError(500);
}
}
private static class Model {
private String username;
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
}
}
When I try to access ${username} in a template, I get the following error.
The following has evaluated to null or missing:
==> username [in template "hello.ftl" at line 8, column 10]
Tip: If the failing expression is known to be legally null/missing... (snip)
The failing instruction (FTL stack trace):
----------
==> ${username} [in template "hello.ftl" at line 8, column 8]
----------
I can get the template to work correctly when I use a Map. I've tried explicitly wrapping the Model object with various TemplateModel wrappers, but nothing I try seems to work.
Any hints?
Model must be a public class for this to work.
Some other notes unrelated to the question: Use setServletContextForTemplateLoading instead setDirectoryForTemplateLoading, or else your app won't work if it's run from an unpacked .war. Also, of course you must not re-create the Configuration for each request, but I assume that's like that only for the sake of this example.