Create a SpecificRecord from an Avro Schema programmatically - avro

I'm working with the following code that takes a org.apache.avro.Schema and returns a org.apache.avro.generic.GenericRecord.
How can I change it to return a org.apache.avro.specific.SpecificRecord instead?
private GenericRecord generateRecord(Schema schema) {
GenericRecordBuilder builder = new GenericRecordBuilder(schema);
for (Schema.Field field : schema.getFields()) {
builder.set(field, generateObject(field.schema()));
}
return builder.build();
}
e.g.
if (schema.getName().equals("MyCustomRecord")) {
// code to create SpecificRecord here from Schema
}

Related

Grails - How do I get the value of a domain entity prop in a function of its parent class

I have an abstract class in a groovy file:
Implementation 1
public abstract class Item {
public String testStr;
public String getBigTestStr(){
String s = "___" + this.testStr;
return s;
}
}
Which is inherited by
class Material extends Item {
public String testStr;
static marshalling = {
detail {
includes "bigTestStr"
}
summary {
includes "bigTestStr"
}
}
static mapping = {
table 'materialset'
id column: 'NODEID'
testStr column: 'MATERIALTYPE'
version false
}
}
The idea is that hitting the endpoint for a material will return the return value of Item.bigTestStr(). However, when I trace through Item.bigTestStr(), the debug's variables table shows a value for this.testStr, but is null when it is added to s. See here:
I tried taking the testStr property out of Material
Implementation 2
class Material extends Item {
static marshalling = {
detail {
includes "bigTestStr"
}
summary {
includes "bigTestStr"
}
}
static mapping = {
table 'materialset'
id column: 'NODEID'
testStr column: 'MATERIALTYPE'
version false
}
}
but I still get the same problem.
For both implementations the endpoint returns
{
bigTestStr: ____null
}
How can I get the actual value of Material.testStr to be used by the function in its parent class?
UPDATE
As Emmanuel pointed out, Implementation 2 is the right way to use properties from a parent class. However, this implementation does not seem to work with mapping the parent class' properties to a database column. So the real question is: How can I get Material.testStr to map to a database column?
It looks like your problem is in how you initialized your Material instance. Here's an example:
public abstract class Item {
public String testStr
public String getBigTestStr(){
"___$testStr"
}
}
class MaterialA extends Item {
public String testStr
static marshalling = {
detail {
includes 'bigTestStr'
}
summary {
includes 'bigTestStr'
}
}
static mapping = {
table 'materialset'
id column: 'NODEID'
testStr column: 'MATERIALTYPE'
version false
}
}
class MaterialB extends Item {
static marshalling = {
detail {
includes 'bigTestStr'
}
summary {
includes 'bigTestStr'
}
}
static mapping = {
table 'materialset'
id column: 'NODEID'
testStr column: 'MATERIALTYPE'
version false
}
}
Shown above are three classes Item, MaterialA, and MaterialB. The two material classes simulate your two tests: MaterialA has a testStr property, while MaterialB inherits a property with the same name from Item instead. Here's what happens when instances of both classes are initialized and getBigTestStr() is tested:
new MaterialA(testStr: 'Hello').with {
assert bigTestStr == '___null'
}
new MaterialB(testStr: 'Hello').with {
assert bigTestStr == '___Hello'
}
In short, your second approach, inheriting the property, works. A super class does not (and should not) have access to anything in its subclasses. It doesn't even know about its subclasses. The approach works because initializing testStr in an instance of MaterialB actually initializes the inherited property from Item; which of course is accessible within the Item class.
In your case, Grails is initializing the instances for you using the values stored in the database. So I'd check your database.
Update
Here's an example using a trait rather than an abstract class:
public trait Item {
String testStr
public String getBigTestStr(){
"___$testStr"
}
}
class Material implements Item {
static marshalling = {
detail {
includes 'bigTestStr'
}
summary {
includes 'bigTestStr'
}
}
static mapping = {
table 'materialset'
id column: 'NODEID'
testStr column: 'MATERIALTYPE'
version false
}
}
new Material(testStr: 'Hello').with {
assert bigTestStr == '___Hello'
}
This makes it so that there's no need for an Item table.

No Adapter for Mapper Unit Test

I have a mapper that uses a \Zend\Db\TableGateway\TableGateway via DI. I have mocked it for the unit test.Here is the test:
class EMSMapperTest extends PHPUnit_Framework_TestCase
{
public function testFetchAllReturnsAllScheduledBlocks()
{
$resultSet = new ResultSet();
$mockTableGateway = $this->getMock(
'Zend\Db\TableGateway\TableGateway',
array('select','getTable'),
array(),
'',
false
);
$mockTableGateway->expects($this->once())
->method('selectWith')
->with()
->will($this->returnValue($resultSet));
$mockTableGateway->expects($this->once())
->method('getTable')
->with()
->will($this->returnValue('table'));
$emsMapper = new EMSMapper($mockTableGateway);
$this->assertSame($resultSet, $emsMapper->fetchAll());
}
}
and the mapper being tested:
class EMSMapper extends BaseMapper
{
public function fetchAll( $building = null,
$room = null, DateRange $range = null )
{
$select = new Select;
$table = $this->tableGateway->getTable();
$select->from($table);
if(!empty($building))
{
$select->where(array('buildingCode'=>$building));
}
if(!empty($room))
{
$select->where(array("room"=>$room));
}
if(is_array($range))
{
if(!empty($range['start']))
{
$select->where("start >= '{$range['start']}'");
}
if(!empty($range['stop']))
{
$select->where("stop <= '{$range['stop']}'");
}
}
$resultSet = $this->tableGateway->selectWith($select);
$results = array();
foreach($resultSet as $r)
{
$results[] = $r;
}
return $results;
}
}
After returning a string from the TableGateway's getTable() method the unit test says:
There was 1 error:
1) EMSTest\Model\EMSMapperTest::testFetchAllReturnsAllScheduledBlocks
Zend\Db\TableGateway\Exception\RuntimeException:
This table does not have an Adapter setup
If would seem that the Select requires the table string supplied to the from() method have an adapter associated with it. How do I supply a mock of the required adapter?
Thanks for the help!
Your code is using the actual code for selectWith. This calls an initialize method that throws your error.
Change you mock code to:
$mockTableGateway = $this->getMock(
'Zend\Db\TableGateway\TableGateway',
array('selectWith','getTable'),
array(),
'',
false
);
This should properly configure your mock.
http://phpunit.de/manual/current/en/test-doubles.html
From the manual:
When the second (optional) parameter is provided, only the methods whose names are in the array are replaced with a configurable test double. The behavior of the other methods is not changed. Providing NULL as the parameter means that no methods will be replaced.
So you were setting the expects on the correct method, but were replacing the wrong one with your mock and so the real code was being executed.

Grails...send/save table data on click of a button

I have a Grails project and I need to send/save table data. I have a controller(doesn't have views) with following code.
class JsonController {
def getCompany = {
for (String s in request.getHeaderNames()) {
println request.getHeader(s)
}
println Company.list()
render Company.list() as XML
}
def getEmployees = {
for (String s in request.getHeaderNames()) {
println request.getHeader(s)
}
render Employees.list() as XML
}
def getManagers = {
for (String s in request.getHeaderNames()) {
println request.getHeader(s)
}
render Managers.list() as XML
}
}
Now I need to call/run these functions on clicking an link and send the output thru email or save to a folder. How can I do this?
Thankyou
Note: the following code requires the mail plugin
I would move your JsonController to a service, which I renamed to XMLService, since that is what you are returning. Then, inject the XMLService in whatever artefacts you want to use it in, such as another service or controller.
import grails.converters.XML;
class XMLService {
def getCompanies = {
return Company.list() as XML
}
def getEmployees = {
return Employees.list() as XML
}
def getManagers = {
return Managers.list() as XML
}
}
Then, in a controller or service. This example uses a service:
class MyMailingService {
def mailService //<-- included from the Mail plugin
def xmlService
void sendEmployeeList(){
mailService.sendMail {
to "fred#g2one.com","ginger#g2one.com"
subject "Hello to mutliple recipients"
body xmlService.getEmployees()
}
}
}
And for storing files, something like the following. Note, that this does not have to be service, but for demonstration purposes, it was easier.
class MyStorageService {
def xmlService
void storeEmployeeList(){
//It was a little unclear how you wanted to store the file, so be careful because this this does not include checks you would want to implement in production (e.g. checks for existing files, possible runtime exceptions, etc).
def f= new File('employees.txt') //see http://docs.codehaus.org/display/GROOVY/JN2015-Files
f << xmlService.getEmployees()
}
}
Noticed you have had answers for email text file - this is how to to store to XML file
where rowid will be the definition for each xml row
def file=""${System.properties['catalina.base']}/file.xml"
try {
new File(file).withWriter { writer ->
def xml = new MarkupBuilder( writer )
def Users = Registeration.list()
xml.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
xml.rowid {
Employees.each { employee ->
xml.registeration(id: employee.id) {
username(employee.username)
//somethingelse(employee.somethingelse)
}
}
}
}
} catch (Exception e) {
result=e.printStackTrace()
}
if (result!=null) {
result="all done stored in "+file
}else{
result="Something has gone wrong with "+file
}

findByPid is not working for pages_language_overlay mapping

(I use typo3 4.5 with extbase-extension.)
I was map the pages_language_overlay to my extbase-model
Tx_Extension_Domain_Model_ModelName {
mapping {
tableName = pages_language_overlay
}
}
I created a model Tx_Extension_Domain_Model_ModelName with some setters and getters. after adding the repository Tx_Extension_Domain_Repository_ModelNameRepository with
public function initializeObject() {
$this->defaultQuerySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$this->defaultQuerySettings->setRespectStoragePage(FALSE);
}
and inject the repository like this
public function injectModelNameRepository(Tx_Extension_Domain_Repository_ModelNameRepository $modelNameRepository) {
$this->modelNameRepository = $modelNameRepository;
}
i can not select entries with findByPid. I was testing it with findByUid and echo the pid and it works, but i get no results with findByPid.
Someone has an idea?
I only have to add
public function initializeObject() {
$this->defaultQuerySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$this->defaultQuerySettings->setRespectStoragePage(FALSE);
$this->defaultQuerySettings->setRespectSysLanguage(FALSE);
}
after this it works well. Otherwise the query has a check like
AND pages_language_overlay.sys_language_uid IN (0,-1)
in the where clause.

Avoiding table changes when mapping legacy database tables in Grails?

I have an applicaton that contains some tables that are auto-generated from Grails domain classes and one legacy table (say table legacy) that have been created outside of Grails but are being mapped by Grails domain classes. Mapping the columns in the legacy database is trivial, but I would like to disable the adding of extra fields and indexes that Grails tries to take care of for said table.
My question is: How do I instruct Grails not to make any table changes to the legacy table (changes such as adding indexes, foreign keys, version columns, etc.)?
Please note that I do not want to disable the automatic schema generation/updating for all tables, only for the mapped table legacy.
The only way I've been able to do stuff like this is a custom Configuration class:
package com.foo.bar;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
public class DdlFilterConfiguration extends GrailsAnnotationConfiguration {
private static final String[] IGNORE_NAMES = { "legacy" };
#Override
public String[] generateSchemaCreationScript(Dialect dialect) throws HibernateException {
return prune(super.generateSchemaCreationScript(dialect), dialect);
}
#Override
public String[] generateDropSchemaScript(Dialect dialect) throws HibernateException {
return prune(super.generateDropSchemaScript(dialect), dialect);
}
#Override
public String[] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata) throws HibernateException {
return prune(super.generateSchemaUpdateScript(dialect, databaseMetadata), dialect);
}
private String[] prune(String[] script, Dialect dialect) {
if (dialect instanceof HSQLDialect) {
// do nothing for test env
return script;
}
List<String> pruned = new ArrayList<String>();
for (String command : script) {
if (!isIgnored(command)) {
pruned.add(command);
}
}
return pruned.toArray(new String[pruned.size()]);
}
private boolean isIgnored(String command) {
command = command.toLowerCase();
for (String table : IGNORED_NAMES) {
if (command.startsWith("create table " + table + " ") ||
command.startsWith("alter table " + table + " ") ||
command.startsWith("drop table " + table + " ")) {
return true;
}
}
return false;
}
}
Put this in src/java (it can't be written in Groovy because of a weird compilation error) and register it in DataSource.groovy using the 'configClass' attribute:
dataSource {
pooled = true
driverClassName = ...
username = ...
password = ...
dialect = ...
configClass = com.foo.bar.DdlFilterConfiguration
}
My solution was a bit simpler.
in the mapping section of the Domain class, I just set version false and I named the 'id' column.
class DomainClass {
static mapping = {
table 'legacyName'
version false
columns{
id column: 'legacy_id'
}
}
}
You can try using Hibernate annotations to specify things such as column name, table, etc instead of creating a normal domain class. For more info see the "Mapping with Hibernate Annotations" section of the following link.
http://www.grails.org/Hibernate+Integration

Resources